home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / MPW 411 / InsideMacintoshHelp < prev    next >
Encoding:
Text File  |  1992-01-28  |  7.3 MB  |  161,197 lines  |  [TEXT/MPS ]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. æKY CopyrightNotice
  2. æC  Copyright Apple Computer, Inc. 1985-1990, All rights reserved.
  3. 411 - Inside Macintosh Help - MPW 3.2 Final Release.
  4. Friday, March 29,1991 9:00:00 AM
  5.  
  6. Information source: SpInsideMacintosh 1.0 HyperCard stack.
  7.                     Pegasus 1.2.5 Hypercard Stack  IM Vol VI
  8.                     Inside Macintosh Volume VI Hypercard Stack
  9. æKY Help
  10. InsideMacintoshHelp
  11. æC 
  12. AboutInsideMacintoshHelp   Preface                   UserInterfaceGuidelines
  13. IntroductionToSystem7.0    RoadMap                   WorldwideSoftwareOverview
  14.                                                      
  15.                      
  16. AliasManager               FontManager               QuickDraw
  17. AppleEventManager          GraphicsDevicesManager    ResourceManager
  18. AppleTalkManager           HelpManager               ScrapManager
  19. ColorManager               ListManager               ScriptManager
  20. ControlManager             MemoryManager             SCSIManager
  21. DataAccessManager          MenuManager               ShutdownManager
  22. DeferredTaskManager        NotificationManager       SlotManager     
  23. DeskManager                OSEventManager            SoundManager 
  24. DeviceManager              PackageManager            StartManager
  25. DialogManager              PaletteManager            TimeManager 
  26. EditionManager             PowerManager              ToolboxEventManager 
  27. EventManager               PrintingManager           VerticalRetraceManager 
  28. FileManager                ProcessManagement         WindowManager
  29.  
  30.  
  31.  
  32. AppleDesktopBus            FloatingPointPackage      SerialDrivers                   
  33. BinaryDecimalConversion    GraphicsOverView          SoundDriver
  34. ColorPickerPackage         InternationalUtilities    StandardFilePackage      
  35. ColorQuickDraw             MacintoshHardware         SystemErrorHandler 
  36. CompatibilityGuidelines    MemoryManagement          SystemResourceFile
  37. ControlPanels              OSUtilities               TextEdit
  38. DiskDriver                 PictureUtilitiesPackage   ToolboxUtilities
  39. DiskInitialization         PPCToolbox                UsingAssemblyLanguage             
  40. FinderInterface            SegmentLoader                                          
  41.  
  42.  
  43.  
  44. CommunicationsResourceManager                         FileTransferManager
  45. ConnectionManager                                        TerminalManager
  46.  
  47.  
  48. ( The Appenices (A-D), SystemErrors and Glossary do not contain information 
  49.  from  "Inside the Macintosh Communications Toolbox")
  50.  
  51. A.ResultCodes              C.SystemTraps             SystemErrors
  52. B.MovesMemory              D.GlobalVariables         Glossary
  53.  
  54.  
  55. æKY AboutInsideMacintoshHelp
  56. æC
  57.  
  58. ------------------------------------------------------------------------------
  59.  Version 1.1 B1  
  60.  
  61.  Added information from 
  62.     "Inside the Macintosh Communications Toolbox"
  63.  
  64.  The appenices (A - D), SystemErrors and Glossary do not contain information 
  65.  from  "Inside the Macintosh Communications Toolbox"
  66. ------------------------------------------------------------------------------
  67.  Version 1.0 Final  
  68.  
  69.  Shipped with MPW 3.2 Final and System 7.0 Final CD releases.
  70.  Includes the latest changes to InsideMacintosh VI document.
  71.  
  72. ------------------------------------------------------------------------------
  73.  Version 1.0 B2 
  74.  
  75.  Shipped on the ETO#3 CD release and System 7.0 B4 CD Release.
  76.  This version has more current Volume VI information. 
  77.  
  78.  
  79. ------------------------------------------------------------------------------
  80.  Version 1.0 B1:
  81.  
  82.  Volume VI chapters have been added to this version which contain information
  83.  about System 7.0, new managers and changes to previous ones. 
  84.  
  85.  New manager chapters are:               
  86.     AppleTalk Manager                                             
  87.     Edition Manager
  88.     Event Manager
  89.     GraphicDevices Manager (Replaces the Graphic Devices chapter in Volume V) 
  90.     Help Manager
  91.     Memory Management
  92.     Power Manager
  93.     PPC Toolbox
  94.     Process Management
  95.  
  96. Changed chapters are:
  97.     Alias Manager 
  98.     Color Picker Package
  99.     Color Quikdraw
  100.     Control Panels
  101.     File Manager
  102.     FinderInterface
  103.     Font Manager
  104.     Notification Manager
  105.     Palette Manager
  106.     Resource Manager
  107.     Slot Manager
  108.     Sound Manager
  109.     TextEdit
  110.     Time Manager
  111.     
  112. New/changed documentation chapters are:
  113.     Compatibility Guidelines
  114.     Graphics Overview
  115.     Introduction to System 7.0
  116.     Preface
  117.     UserInterface Guidelines VI
  118.     Worldwide Software Overview
  119.  
  120. ------------------------------------------------------------------------------
  121.  Version 1.0 Alpha:
  122.  
  123.  InsideMacintoshHelp file provides on-line documentation for the 411 project.
  124.  This version contains all the chapters of InsideMacintosh Volumes I - V.  
  125.  
  126.  
  127. æKY AliasManager
  128. æC 
  129. _______________________________________________________________________________
  130.  
  131. THE ALIAS MANAGER
  132. _______________________________________________________________________________
  133.  
  134. About…the…Alias…Manager…Chapter…Volume…VI
  135. About…the…Alias…Manager…Volume…VI
  136. About…Alias…Records…Volume…VI
  137. Search…Strategies3.…Volume…VI
  138.     Fast…Search
  139.     Exhaustive…Search
  140. Using…the…Alias…Manager…Volume…VI
  141.     Creating…Alias…Records
  142.     Resolving…Alias…Records
  143.         Resolvealias
  144.         Matchalias
  145.     Maintaining…Alias…Records
  146.     Getting…Information…About…Alias…Records
  147.     Customizing…Alias…Records
  148. Alias…Manager…Routines…Volume…VI
  149.     Creating…and…Updating…Alias…Records
  150.     Resolving…and…Reading…Alias…Records
  151.     Filtering…Possible…Targets
  152. Summary…of…the…Alias…Manager…Volume…VI
  153.     Alias…Manager…Constants
  154.     Alias…Manager…Data…Types
  155.     Alias…Manager…Routines…Summary
  156.     Alias…Manager…Application-Defined…Routine
  157.     Alias…Manager…Result…Codes
  158.     Alias…Manager…Assembly-Language…Information
  159. _______________________________________________________________________________
  160.  
  161.  
  162.  
  163. æKY About…the…Alias…Manager…Chapter…Volume…VI
  164. æC »About the Alias Manager Chapter Volume VI                            The Alias Manager
  165. _______________________________________________________________________________
  166.  
  167. This chapter describes how your application can use the Alias Manager to
  168. establish and resolve alias records, which are data structures that describe
  169. file system objects (that is, files, directories, and volumes).
  170.  
  171. You create an alias record to take a fingerprint of a file system object,
  172. usually a file, that you might need to locate again later. You can store the
  173. alias record, instead of a standard file specification, and then let the Alias
  174. Manager find the file again when it’s needed. The Alias Manager contains
  175. algorithms for locating files that have been moved, renamed, copied, or restored
  176. from backup.
  177.  
  178.    Note:  The Alias Manager lets you exploit alias records. It does not directly
  179.  
  180.    manipulate Finder™ aliases, which are created and managed by the user through
  181.    the Finder. The Finder Interface chapter describes Finder aliases and how
  182.    your 
  183.    application can accommodate them.
  184.  
  185. The Alias Manager is available only in system software version 7.0 or later.
  186. Call the Gestalt function, described in the Compatibility Guidelines chapter of
  187. this volume, to determine whether the Alias Manager is present.
  188.  
  189. Read this chapter if you want your application to create and resolve alias
  190. records. You might store an alias record, for example, to identify a customized
  191. dictionary from within a word-processing document. When the user runs a spelling
  192. checker on the document, your application can ask the Alias Manager to resolve
  193. the record to find the correct dictionary.
  194.  
  195. To use this chapter, you should be familiar with the File Manager’s conventions
  196. for identifying files, directories, and volumes, as described in the File
  197. Manager chapter in this volume.
  198.  
  199. _______________________________________________________________________________
  200.  
  201. æKY About…the…Alias…Manager…Volume…VI
  202. æC »About the Alias Manager Volume VI                                    The Alias Manager
  203. _______________________________________________________________________________
  204.  
  205. The Alias Manager creates and resolves alias records. The next section, “About
  206. Alias Records,” describes how you can use alias records.
  207.  
  208. In general, you should use the Alias Manager to create an alias record whenever
  209. you find yourself storing a specific file description, such as filename and
  210. parent directory ID. The Alias Manager stores this information and more in the
  211. alias record, and it also provides a set of search strategies for resolving the
  212. record later. The search strategies are described later in this chapter in
  213. “Resolving Alias Records.”
  214.  
  215. You can use the Alias Manager to
  216.  
  217.    • create alias records
  218.  
  219.    • resolve alias records
  220.  
  221.    • update alias records
  222.  
  223.    • get information about alias records
  224.  
  225. The Alias Manager can track files and directories across volumes. If the target
  226. of an alias record is on an unmounted AppleShare® volume, the Alias Manager
  227. automatically mounts the volume when it resolves the alias. If the target object
  228. is on an unmounted ejectable volume, the Alias Manager prompts the user to
  229. insert the volume.
  230.  
  231. When the Alias Manager creates an alias record, it allocates the storage, fills
  232. in the record, and returns a handle to it. Your application is responsible for
  233. storing the record and retrieving it when needed. Your application must also
  234. supply strategies for handling various alias-resolution problems, described in
  235. “Resolving Alias Records.”
  236.  
  237. To help you understand and use the Alias Manager, this chapter provides
  238.  
  239.    • an overview of alias records
  240.  
  241.    • a description of how the Alias Manager resolves alias records
  242.  
  243.    • specific techniques for using the Alias Manager in your application
  244. _______________________________________________________________________________
  245.  
  246. æKY About…Alias…Records…Volume…VI
  247. æC »About Alias Records Volume VI                                        The Alias Manager
  248. _______________________________________________________________________________
  249.  
  250. An alias record is a data structure that describes a file, directory, or volume.
  251. The record contains
  252.  
  253.    • location information, such as name and parent directory ID
  254.  
  255.    • verification information, such as creation date, file type, and creator
  256.  
  257.    • volume mounting information (that is, server and zone), if applicable
  258.  
  259. By storing alias records, you can allow your users to create a robust connection
  260. to a file—that is, a connection that can survive the moving or renaming of the
  261. target file. The Finder in system software version 7.0, for example, stores
  262. alias records in aliases created by the user to represent other files or
  263. folders. The Edition Manager uses alias records to support data-sharing among
  264. separate documents. (The Finder Interface and Edition Manager chapters in this
  265. volume describe those features in detail.)
  266.  
  267. An alias record is a reliable way to identify a file system object when your
  268. application is communicating with a process that might be running on a different
  269. machine.
  270.  
  271. The creation of an alias record has no effect on the target of the record,
  272. except to establish a file ID if one did not previously exist for the target
  273. file. (See the File Manager chapter of this volume for a description of file
  274. IDs.)
  275.  
  276. The alias record contains only two fields of public information available to
  277. your application. The bulk of the record is managed privately by the Alias
  278. Manager.
  279.  
  280.    TYPE AliasRecord =
  281.         RECORD
  282.            userType:   OSType;   {application’s signature}
  283.            aliasSize:  Integer;  {size of record when created}
  284.            {variable-length private data}
  285.         END;
  286.  
  287. Your application can use the userType field to store its own signature or any
  288. other data that fits into 4 bytes. When the Alias Manager creates an alias
  289. record, it stores 0 in that field.
  290.  
  291. The Alias Manager stores the size of the record when it was created in the
  292. aliasSize field. Knowing the starting size allows you to store and retrieve data
  293. of your own at the end of the record (see “Customizing Alias Records” later in
  294. this chapter). An alias record is typically 200 to 300 bytes long.
  295.  
  296. The private Alias Manager data includes all of the location, verificiation, and
  297. mounting information needed to resolve the alias record with the various search
  298. strategies described in this chapter.
  299.  
  300. When you create an alias record, you have the option of recording a relative
  301. path, that is, the path to the target from another file or directory on the same
  302. volume. (Relative path doesn’t work across volumes.) The beginning point of a
  303. relative path is called the fromFile. To record a relative path, the Alias
  304. Manager saves the distances from the target and the fromFile to their common
  305. parent, that is, the lowest-level directory that appears in the pathnames of
  306. both. The Alias Manager can later use those distances in conjunction with the
  307. full pathname to conduct a relative search.
  308.  
  309. Suppose, for example, that you are writing a word-processing application that
  310. allows the user to build a customized, supplemental dictionary for each
  311. document. You create the dictionary as a separate document in the same directory
  312. as the document it serves, as Figure  27-1 shows.
  313.  
  314. ¿ Figure 27-1   Resolving a relative path ø 
  315.  
  316. When resolving the alias record by using a relative path, the Alias Manager
  317. starts at the directory that is the specified distance above the fromFile, the
  318. directory named Sample in the example in Figure 27-1. The Alias Manager then
  319. constructs a partial pathname by extracting one field of the absolute pathname
  320. for each step from the target to the common parent. In this example, the
  321. distance is one, so the pathname contains only the name of the target document,
  322. Dictionary.
  323.  
  324. In some circumstances, a relative search identifies the correct target when a
  325. direct search cannot. For example, suppose the user of your word-processing
  326. application creates a working copy of a document and dictionary by copying the
  327. entire folder Sample to another disk. The user later updates the original
  328. document and dictionary by copying the folder from the working disk. All of the
  329. underlying file and directory identifications change, but the filenames and
  330. relative path remain the same. When the user later runs the spelling checker on
  331. the document, a relative-path search finds the correct target dictionary.
  332.  
  333. The Alias Manager accepts and returns file specifications in the form of file
  334. system specification records (FSSpec records), described in the File Manager
  335. chapter of this volume. The FSSpec record represents a standard, complete
  336. description of a file system object. It contains a volume reference number, a
  337. parent directory ID, and a name.
  338.  
  339. _______________________________________________________________________________
  340.  
  341. æKY Search…Strategies3.…Volume…VI
  342. æC »Search Strategies3. Volume VI                                        The Alias Manager
  343. _______________________________________________________________________________
  344.  
  345. One of the key features of the Alias Manager is the search strategies built into
  346. the alias-resolution functions. The search strategies are designed to find the
  347. original target of an alias record, even if the target has been moved, renamed,
  348. copied, or restored from backup.
  349.  
  350. The Alias Manager provides two basic alias-resolution algorithms: a fast search
  351. and an exhaustive search. This section describes the search algorithms. For
  352. descriptions of the functions that perform the searches, see “Resolving Alias
  353. Records” and “Resolving and Reading Alias Records” later in this chapter.
  354.  
  355. The first step in any nonrelative search is to identify the volume on which the
  356. target resides. The volume search considers the volume’s name, creation date
  357. (which acts almost as a unique identifier for a volume), and type (for example,
  358. a hard disk, a 3.5-inch floppy disk, or an AppleShare volume).
  359.  
  360. The Alias Manager first looks for a volume that matches all three criteria:
  361. name, creation date, and type. The search succeeds if the volume is mounted and
  362. if its name and creation date have not changed since the record was created. If
  363. the search fails, the Alias Manager attempts to match by creation date and type
  364. only. This step locates volumes that have been renamed. Finally, the Alias
  365. Manager attempts to match by volume name and type only.
  366.  
  367. If the target is on an unmounted AppleShare volume, the Alias Manager attempts
  368. to mount the volume. It presents a name and password dialog if appropriate. If
  369. the target is on an unmounted ejectable volume, the Alias Manager displays a
  370. dialog box prompting the user to insert the volume. Your application can
  371. suppress the automatic mounting, as explained in the description of the
  372. MatchAlias function in “Alias Manager Routines.”
  373. _______________________________________________________________________________
  374.  
  375. æKY Fast…Search
  376. æC »Fast Search                                                          The Alias Manager
  377. _______________________________________________________________________________
  378.  
  379. The fast-search algorithm is designed to find the target of an alias record
  380. quickly.
  381.  
  382. Depending on how you invoke it, the fast-search algorithm starts with either a
  383. relative search (described earlier in “About Alias Records”) or a direct search
  384. (described in this section).  Fast search can perform a relative search whether
  385. or not it has identified the target volume, but it must identify the volume
  386. before it can perform a direct search.
  387.  
  388. In a direct search, the fast-search algorithm first looks for the target by file
  389. ID (if the target is a file) or directory ID (if the target is a directory).
  390. (File IDs and directory IDs are described in the File Manager chapter of this
  391. volume.) Even if a file has been renamed or moved on a volume, the Alias Manager
  392. can find it quickly through its file ID.
  393.  
  394. If the search by file ID or directory ID fails, fast search looks for the target
  395. by name in the original parent directory. This search locates the target if its
  396. file or directory ID has changed but it still exists by the same name in the
  397. parent directory (for example, if the target was restored from backup). Fast
  398. search compares file numbers on files found by name in the correct parent
  399. directory. If the file numbers do not match, the file is treated as a possible
  400. match, that is, it is put on the list of candidates and the search continues. If
  401. the target is not found by name in the parent directory, fast search looks for a
  402. file by file number in the parent directory. A file with the same file number
  403. but a different name replaces a file with the same name but a different file
  404. number in the list of matches.
  405.  
  406. If the search by file ID or directory ID fails and if fast search cannot find
  407. the original parent directory, it searches for the target by full pathname. This
  408. search finds the target if it resides in the same location on the volume but the
  409. directory ID of its parent directory has changed (for example, if the entire
  410. parent directory was restored from backup).
  411.  
  412. If the search by full pathname fails, fast search attempts to find the file by
  413. tracing partial pathnames up through all parent directories, using parent
  414. directory IDs instead of directory names. For example, consider this full
  415. pathname:
  416.  
  417. Loma Prieta:MyReports:October:Sales Report
  418.  
  419. If the search by full pathname fails, fast search first looks for the partial
  420. pathname :Sales Report in the directory with the ID that the directory Loma
  421. Prieta:MyReports:October had when the alias record was created. If that search
  422. fails, it looks for :October:Sales Report in the directory with the ID that Loma
  423. Prieta:MyReports had, and so on.
  424.  
  425. If you did not ask for a search by relative path first but did provide a
  426. starting point for a relative search, and if the alias record contains relative
  427. path information, fast search performs a relative search after the direct
  428. search. The relative search succeeds if the relative path is the same as when
  429. the record was created and if the names of the target and its intervening parent
  430. directories have not changed.
  431.  
  432. _______________________________________________________________________________
  433.  
  434. æKY Exhaustive…Search
  435. æC »Exhaustive Search                                                    The Alias Manager
  436. _______________________________________________________________________________
  437.  
  438. The exhaustive-search algorithm scans an entire volume to look for possible
  439. matches.
  440.  
  441. The Alias Manager typically performs an exhaustive search by calling the File
  442. Manager function PBCatSearch, searching for files or directories with a matching
  443. creation date, creator, and type. (See the File Manager chapter of this volume
  444. for a description of PBCatSearch.)
  445.  
  446. PBCatSearch is available only on HFS volumes, not on MFS volumes. (See the File
  447. Manager chapter of this volume for a description of the two file systems.)
  448. PBCatSearch is also available only on systems running version 7.0 and later.
  449. When PBCatSearch is not available, exhaustive search performs a search of the
  450. entire volume by making a series of indexed File Manager calls, searching for
  451. objects with matching creation date, type, creator, or file number.
  452.  
  453. _______________________________________________________________________________
  454.  
  455. æKY Using…the…Alias…Manager…Volume…VI
  456. æC »Using the Alias Manager Volume VI                                    The Alias Manager
  457. _______________________________________________________________________________
  458.  
  459. You use the Alias Manager primarily to create and resolve alias records. You can
  460. also use it to get information about and update alias records.
  461.  
  462. The Alias Manager creates an alias record in memory and provides you with a
  463. handle to the record. When you no longer need a record in memory, free the
  464. memory by calling the DisposHandle procedure, described in the Memory Manager
  465. chapter of Volume II. You can store and retrieve alias records as resources of
  466. type 'alis'.
  467.  
  468. Alias Manager functions accept and return file specifications in the form of
  469. FSSpec records, which contain a volume reference number, a parent directory ID,
  470. and a target name. See the File Manager chapter in this volume for a description
  471. of file identification conventions.
  472.  
  473. Before calling any of the Alias Manager functions, verify that the Alias Manager
  474. is available by calling the Gestalt function with a selector of
  475. gestaltAliasMgrAttr. If Gestalt sets the gestaltAliasMgrPresent bit in the
  476. response, the Alias Manager is present. For a complete description of the
  477. Gestalt function, see the Compatibility Guidelines chapter of this volume.
  478.  
  479. For more detailed descriptions of the functions described in this section, see
  480. “Alias Manager Routines” later in this chapter.
  481.  
  482. _______________________________________________________________________________
  483.  
  484. æKY Creating…Alias…Records
  485. æC »Creating Alias Records                                               The Alias Manager
  486. _______________________________________________________________________________
  487.  
  488. You create a new alias record by calling one of three functions: NewAlias,
  489. NewAliasMinimal, or NewAliasMinimalFromFullpath. The NewAlias function creates a
  490. complete alias record that can make full use of the alias-resolution algorithms.
  491. The other two functions are streamlined variations designed for circumstances
  492. when speed is more important than robust resolution services. All three
  493. functions allocate the memory for the record, fill it in, and provide a handle
  494. to it.
  495.  
  496. NewAlias always records the name and the file or directory ID of the target, its
  497. creation date, the parent directory name and ID, and the volume name and
  498. creation date. It also records the full pathname of the target and a collection
  499. of other information. You can request that NewAlias store relative path
  500. information as well by supplying a starting point for a relative path (see
  501. “About Alias Records” earlier in this chapter for a description of relative
  502. path).
  503.  
  504. Call NewAlias when you want to create an alias record to store for later use.
  505. For example, suppose you are writing a word-processing application that allows
  506. the user to customize a dictionary for use with a single text file. Your
  507. application stores the custom data in a separate dictionary file in the same
  508. directory as the document. As soon as you create the dictionary file, you call
  509. NewAlias to create an alias record for that file, including path information
  510. relative to the user’s text file:
  511.  
  512. MyErr := NewAlias(textFile, target, myAliasHdl);
  513.  
  514. The textFile parameter is a pointer to a file system specification record that
  515. identifies the starting point for the relative search, in this case the user’s
  516. text file. If you do not want relative path information recorded, pass a value
  517. of NIL in the first parameter.
  518.  
  519. The target parameter is a file system specification record that identifies the
  520. target file, in this example the dictionary file.
  521.  
  522. The myAliasHdl parameter is a variable in which the Alias Manager returns the
  523. handle to the alias record that describes the target.
  524.  
  525. The two variations on the NewAlias function, NewAliasMinimal and
  526. NewAliasMinimalFromFullpath, record only a minimum of information about the
  527. target. NewAliasMinimal records only the target’s name, parent directory ID,
  528. volume name and creation date, and the volume mounting information.
  529. NewAliasMinimalFromFullpath records only the full pathname of the target,
  530. including the volume name.
  531.  
  532. Use NewAliasMinimal or NewAliasMinimalFromFullpath when you are willing to give
  533. up robust alias-resolution service in return for speed. The Finder, for example,
  534. stores minimal aliases in the Apple events that tell your application to open or
  535. print a document. Because the alias record is resolved almost immediately, the
  536. description is likely to remain valid, and the shorter record is probably safe.
  537.  
  538. You can use NewAliasMinimalFromFullpath to create an alias record for a target
  539. that doesn’t exist or that resides on an unmounted volume.
  540.  
  541. _______________________________________________________________________________
  542.  
  543. æKY Resolving…Alias…Records
  544. æC »Resolving Alias Records                                              The Alias Manager
  545. _______________________________________________________________________________
  546.  
  547. The Alias Manager provides two alias-resolution functions:
  548.  
  549.    • the high-level function ResolveAlias, which performs a fast search and 
  550.       identifies only one target
  551.  
  552.    • the low-level function MatchAlias, which can perform a fast search, an 
  553.       exhaustive search, or both, and which can return a list of target
  554.       candidates
  555.  
  556. In general, when you want to identify only the single most likely target of an
  557. alias record, you call ResolveAlias. You call MatchAlias when you want your
  558. program to control the search.
  559.  
  560. This section describes the alias-resolution functions. The section “Search
  561. Strategies for Resolving Alias Records,” earlier in this chapter, describes the
  562. underlying fast and exhaustive searches.
  563.  
  564. _______________________________________________________________________________
  565.  
  566. æKY Resolvealias
  567. æC »Resolvealias                                                         The Alias Manager
  568. _______________________________________________________________________________
  569.  
  570. Typically, you call the ResolveAlias function to resolve an alias record.
  571. ResolveAlias performs a fast search (described earlier in “Strategies for
  572. Resolving Alias Records”) and exits after it identifies one target.
  573.  
  574. By calling low-level functions, ResolveAlias compares some key information about
  575. the identified target with the information stored in the alias record. If any of
  576. the information is different, ResolveAlias automatically updates the record.
  577.  
  578.    Note:  As with all other Alias Manager functions, ResolveAlias updates the 
  579.    record only in memory. Your application is responsible for updating alias
  580.    records 
  581.    stored on disk when appropriate.
  582.  
  583. In the dictionary example, illustrated in Figure  27-1 earlier in the chapter,
  584. the application calls ResolveAlias when the user runs the spelling checker on a
  585. document with a customized dictionary.
  586.  
  587. MyErr := ResolveAlias(textFile, myAliasHdl, target, wasChanged);
  588.  
  589. The textFile parameter is a pointer to a file system specification record that
  590. identifies the starting point for the relative search, in this case the user’s
  591. text file. If you do not want relative path information used in the search, pass
  592. a value of NIL in the first parameter. If you provide a relative starting point,
  593. ResolveAlias performs the relative search first.
  594.  
  595. The myAliasHdl parameter is a handle to the alias record to be resolved. In this
  596. example, the alias record describes the dictionary file.
  597.  
  598. The target parameter is the file system specification record where the Alias
  599. Manager places the results of its search. After ResolveAlias completes, target
  600. contains the specification for the dictionary file.
  601.  
  602. The ResolveAlias function uses the wasChanged parameter to report whether or not
  603. it updated the alias record. After ResolveAlias completes, wasChanged is TRUE if
  604. the record was updated and FALSE if it was not. If you are storing the alias
  605. record, check the value of wasChanged (as well as the function’s result code) to
  606. see whether to update the stored record after resolving an alias.
  607.  
  608. If ResolveAlias can’t resolve the alias record, it returns a non-zero result
  609. code. A result code of fnfErr signals that ResolveAlias has found the correct
  610. volume and parent directory but not the target file or folder. In this case,
  611. ResolveAlias constructs a valid FSSpec record that describes the target. You can
  612. use this record to explore possible solutions to the resolution failure. You
  613. can, for example, use the FSSpec record to create a replacement for a missing
  614. file with the File Manager function FSpCreate.
  615.  
  616. _______________________________________________________________________________
  617.  
  618. æKY Matchalias
  619. æC »Matchalias                                                           The Alias Manager
  620. _______________________________________________________________________________
  621.  
  622. The MatchAlias function is a low-level routine that gives your application
  623. control over the searching algorithm.
  624.  
  625. You can control
  626.  
  627.    • whether to attempt an automatic mounting of unmounted volumes
  628.  
  629.    • whether to search on more than one volume
  630.  
  631.    • whether to perform a fast search, an exhaustive search, or both
  632.  
  633.    • the order of the direct and relative searches in a fast search
  634.  
  635.    • whether to pursue search strategies that require interaction with the user
  636.    (such 
  637.       as asking for a password while mounting an AppleShare volume)
  638.  
  639. You can also specify a maximum number of candidates that MatchAlias can
  640. identify.
  641.  
  642. See “Alias Manager Routines” later in this chapter for details about controlling
  643. a search with the MatchAlias function.
  644.  
  645. You can supply an optional filter function which MatchAlias calls
  646.  
  647.    • each time it identifies a possible match
  648.  
  649.    • when three seconds have elapsed without a match
  650.  
  651. The filter function determines whether or not each candidate is added to the
  652. list of possible targets. It can also terminate the search. See “Filtering
  653. Possible Targets” later in this chapter for a description of the filter
  654. function.
  655.  
  656. MatchAlias returns all candidates that it identifies in an array of file system
  657. specification records.
  658.  
  659. _______________________________________________________________________________
  660.  
  661. æKY Maintaining…Alias…Records
  662. æC »Maintaining Alias Records                                            The Alias Manager
  663. _______________________________________________________________________________
  664.  
  665. You can store alias records as resources of type 'alis'.
  666.  
  667.    CONST  rAliasType = 'alis';
  668.  
  669. To store and retrieve resources, use the standard Resource Manager functions
  670. (AddResource, GetResource, and GetNamedResource) described in the Resource
  671. Manager chapter of Volume I.
  672.  
  673. To update an alias record, use the UpdateAlias function. You typically call
  674. UpdateAlias any time you know that the target of an alias record has been
  675. renamed or otherwise changed.
  676.  
  677. You are most likely to call UpdateAlias after a call to the MatchAlias function.
  678. If MatchAlias identifies a single target, it sets a flag telling you whether or
  679. not the key information about the target file matches the information in the
  680. alias record. It is the responsibility of your application to update the record.
  681.  
  682. The ResolveAlias function automatically updates an alias record if any of the
  683. the key information about the identified target does not match the information
  684. in the record.
  685.  
  686. _______________________________________________________________________________
  687.  
  688. æKY Getting…Information…About…Alias…Records
  689. æC »Getting Information About Alias Records                              The Alias Manager
  690. _______________________________________________________________________________
  691.  
  692. To retrieve information from an alias record without actually resolving the
  693. record, call the GetAliasInfo function. You can use GetAliasInfo to retrieve the
  694. name of the target, the names of the target’s parent directories, the name of
  695. the target’s volume, or, in the case of an AppleShare volume, its zone or server
  696. name.
  697.  
  698. _______________________________________________________________________________
  699.  
  700. æKY Customizing…Alias…Records
  701. æC »Customizing Alias Records                                            The Alias Manager
  702. _______________________________________________________________________________
  703.  
  704. An alias record contains two kinds of information: public information available
  705. to your application and private information available only to the Alias Manager.
  706. Your application can use the first field, userType, to store its own signature
  707. or any other data that fits into 4 bytes. Your application can use the second
  708. field, aliasSize, to customize the alias record for storing additional data.
  709.  
  710. The Alias Manager stores the size of the record when it is created or updated in
  711. the aliasSize field. To customize an alias record, you first increase the size
  712. of the record with the SetHandleSize procedure, described in the Memory Manager
  713. chapter of Volume II. You can then find the starting address of your own data in
  714. the record by adding the record’s starting address to the length recorded in the
  715. aliasSize field. If you expand the record through the Memory Manager, the Alias
  716. Manager preserves your data, even if it changes the size of its own data when
  717. updating the record.
  718.  
  719. In general, you should customize only alias records that you have created.
  720.  
  721. _______________________________________________________________________________
  722.  
  723. æKY Alias…Manager…Routines…Volume…VI
  724. æC »Alias Manager Routines Volume VI                                     The Alias Manager
  725. _______________________________________________________________________________
  726.  
  727. This section describes the routines you use to create, update, resolve, and read
  728. alias records.
  729.  
  730. Alias Manager routines use file system specification records (FSSpec records) to
  731. identify files, directories, and volumes. To create a FSSpec record, call the
  732. function MakeFSSpec, described in the File Manager chapter of this volume.
  733.  
  734. The Alias Manager routines can return the result codes listed in this section or
  735. any other applicable file-system or memory-management result codes.
  736.  
  737.  
  738.  
  739.  
  740.  
  741.  
  742.  
  743. _______________________________________________________________________________
  744.  
  745. æKY Creating…and…Updating…Alias…Records
  746. æC »Creating and Updating Alias Records                                  The Alias Manager
  747. _______________________________________________________________________________
  748.  
  749. You use the NewAlias function to create a complete alias record.
  750.  
  751. FUNCTION NewAlias (fromFile: FSSpecPtr; target: FSSpec;
  752.                    VAR alias: AliasHandle) : OSErr;
  753.  
  754. NewAlias creates an alias record that describes the specified target. It
  755. allocates the storage, fills in the record, and puts a record handle in the
  756. alias parameter. NewAlias always records the name and file or directory ID of
  757. the target, its creation date, the parent directory name and ID, and the volume
  758. name and creation date. It also records the full pathname of the target and a
  759. collection of other information relevant to locating the target, verifying the
  760. target, and mounting the target’s volume, if necessary. You can request that it
  761. store relative path information as well by supplying a starting point for a
  762. relative path (see “About Alias Records” for a description of relative path).
  763.  
  764. The fromFile parameter represents the starting point for a relative path, to be
  765. used later in a relative search. If you do not need relative path information in
  766. the record, pass a fromFile value of NIL. If you want NewAlias to record
  767. relative path information, pass a pointer to a valid FSSpec record in this
  768. parameter. The two files or directories, fromFile and target, must reside on the
  769. same volume.
  770.  
  771. The target parameter is a FSSpec record for the target of the alias record.
  772.  
  773. NewAlias puts a handle to the newly created alias record in the alias parameter.
  774. If the function fails to create an alias record, it sets alias to NIL.
  775.  
  776. You use the NewAliasMinimal function to create a short alias record quickly.
  777.  
  778. FUNCTION NewAliasMinimal (target: FSSpec; VAR alias: AliasHandle) : 
  779.                           OSErr;
  780.  
  781. NewAliasMinimal creates an alias record that contains only the minimum
  782. information necessary to describe the target: the target name, the parent
  783. directory ID, the volume name and creation date, and the volume mounting
  784. information. NewAliasMinimal uses the standard alias record data structure, but
  785. fills in only parts of the record.
  786.  
  787. The target parameter points to a FSSpec record for the target of the alias
  788. record.
  789.  
  790. NewAliasMinimal puts a handle to the newly created alias record in the alias
  791. parameter. If the function fails to create an alias record, it sets alias to
  792. NIL.
  793.  
  794. The ResolveAlias function, described in “Resolving and Reading Alias Records”
  795. later in this chapter, never updates a minimal alias record.
  796.  
  797. You use the function NewAliasMinimalFromFullpath to quickly create an alias
  798. record that contains only the full pathname of the target.
  799.  
  800. FUNCTION NewAliasMinimalFromFullpath (fullpathLength: Integer;
  801.                                       fullpath: Ptr; zoneName: Str32; 
  802.                                       serverName: Str31;
  803.                                       VAR alias: AliasHandle) : OSErr;
  804.  
  805. NewAliasMinimalFromFullpath creates an alias record that identifies the target
  806. by full pathname. You can call NewAliasMinimalFromFullpath to create an alias
  807. record for a file that doesn’t exist or that resides on an unmounted volume.
  808. NewAliasMinimalFromFullpath uses the standard alias record data structure, but
  809. it fills in only the information provided in the input parameters. You can
  810. therefore use NewAliasMinimalFromFullpath to create alias records for targets on
  811. unmounted volumes.
  812.  
  813. The fullpathLength parameter identifies the number of characters in the full
  814. pathname.
  815.  
  816. The fullpath parameter is a pointer to a buffer that contains the full pathname
  817. of the target. The full pathname starts with the name of the volume, includes
  818. all of the directory names in the path to the target, and ends with the target
  819. name. (For a description of pathnames, see the File Manager chapter in this
  820. volume.)
  821. The parameters zoneName and serverName are strings that identify the AppleTalk
  822. zone and server name of the AppleShare volume on which the target resides. Set
  823. these parameters to null strings if you do not need them.
  824.  
  825. NewAliasMinimalFromFullpath puts a handle to the newly created alias record in
  826. the alias parameter. If the function fails to create an alias record, it sets
  827. alias to NIL.
  828.  
  829. You use the UpdateAlias function to update an alias record.
  830.  
  831. FUNCTION UpdateAlias (fromFile: FSSpecPtr; target: FSSpec;
  832.                       alias: AliasHandle; VAR wasChanged: Boolean) : 
  833.                       OSErr;
  834.  
  835. UpdateAlias updates the alias record pointed to by the alias parameter so that
  836. it describes the target specified by the target parameter. UpdateAlias rebuilds
  837. the entire alias record, filling it in as the NewAlias function would.
  838.  
  839. The fromFile parameter represents the starting point for a relative path, to be
  840. used later in a relative search. If you do not need relative path information in
  841. the record, pass a fromFile value of NIL. If you want UpdateAlias to record
  842. relative path information, pass a pointer to a valid FSSpec record in this
  843. parameter. The two files or directories, fromFile and target, must reside on the
  844. same volume.
  845.  
  846. The target parameter is the target of the alias record. This parameter must be a
  847. valid FSSpec record.
  848.  
  849. The alias parameter is a handle to the alias record to be updated.
  850.  
  851. If the newly constructed alias record is exactly the same as the old one,
  852. UpdateAlias sets the wasChanged parameter to FALSE. Otherwise, it sets it to
  853. TRUE. Check this parameter to determine whether you need to save an updated
  854. record.
  855.  
  856. UpdateAlias always creates a complete alias record. When you update a minimal
  857. alias record with UpdateAlias, you convert the minimal record to a complete
  858. record.
  859.  
  860.    Result codes
  861.    paramErr         –50         target, alias, or both are NIL, or the alias
  862.    record is corrupt
  863. _______________________________________________________________________________
  864.  
  865. æKY Resolving…and…Reading…Alias…Records
  866. æC »Resolving and Reading Alias Records                                  The Alias Manager
  867. _______________________________________________________________________________
  868.  
  869. You use the ResolveAlias function to identify the single most likely target of
  870. an alias record. 
  871.  
  872. FUNCTION ResolveAlias (fromFile: FSSpecPtr; alias: AliasHandle;
  873.                        VAR target: FSSpec; VAR wasChanged: Boolean) : 
  874.                        OSErr;
  875.  
  876. ResolveAlias performs a fast search for the target of the alias, as described
  877. earlier in “Search Strategies for Resolving Alias Records.” If the resolution is
  878. successful, ResolveAlias returns the FSSpec record for the target file system
  879. object through the target parameter, updates the alias record if necessary, and
  880. reports whether or not the record was updated through the wasChanged parameter.
  881. If the target is on an unmounted AppleShare volume, ResolveAlias automatically
  882. mounts the volume. If the target is on an unmounted ejectable volume,
  883. ResolveAlias asks the user to insert the volume. ResolveAlias exits after it
  884. finds one acceptable target.
  885.  
  886. The fromFile parameter represents the starting point for a relative search. If
  887. you pass a fromFile parameter of NIL, ResolveAlias performs only a direct
  888. search. If you pass a pointer to a valid FSSpec record in the fromFile
  889. parameter, ResolveAlias performs a relative search for the target, followed by a
  890. direct search only if the relative search fails. If you want to perform a direct
  891. search followed by a relative search, you must use the MatchAlias function.
  892.  
  893. The alias parameter is a handle to the alias record to be resolved and, if
  894. necessary, updated.
  895.  
  896. The target parameter receives the FSSpec record of the target file system
  897. object.
  898.  
  899. After it identifies a target, ResolveAlias compares some key information about
  900. the target with the information in the alias record. (The upcoming description
  901. of the MatchAlias function lists the key information.) If the information is
  902. different, ResolveAlias updates the record to match the target. If it updates
  903. the alias record, ResolveAlias sets the wasChanged parameter to TRUE. Otherwise,
  904. it sets it to FALSE. (Because ResolveAlias never updates a minimal alias, it
  905. never sets wasChanged to TRUE when resolving a minimal alias.)
  906.  
  907. When it finds the specified volume and parent directory but fails to find the
  908. target file or directory in that location, ResolveAlias returns a result code of
  909. fnfErr and fills in the target parameter with a complete FSSpec record
  910. describing the target (that is, the volume reference number, parent directory
  911. ID, and file or folder name). The FSSpec record is valid, although the object it
  912. describes does not exist. This information is intended as a “hint” that lets you
  913. explore possible solutions to the resolution failure. You can, for example, use
  914. the FSSpec record to create a replacement for a missing file with the File
  915. Manager function FSpCreate.
  916.  
  917. ResolveAlias displays the standard dialog boxes when it needs input from the
  918. user, such as a name and password for mounting a remote volume. The user can
  919. cancel the resolution through these dialog boxes.
  920.  
  921.       Result codes
  922.              dirNFErr                –120         Parent directory not found
  923.              fnfErr                        –43         Target not found, but
  924.              volume and parent 
  925.                                                                directory found;
  926.                                                                target parameter
  927.                                                                contains a 
  928.                                                                valid FSSpec
  929.                                                                record
  930.              nsvErr                       –35        Volume not found
  931.              paramErr                  –50        The alias parameter is NIL, or
  932.              the alias record is 
  933.                                                                corrupt
  934.              usrCanceledErr     –128         The user cancelled
  935.  
  936. You use the MatchAlias function to identify a list of possible matches and pass
  937. the list through an optional selection filter. The filter can pass more than one
  938. possible match.
  939.  
  940. FUNCTION MatchAlias (fromFile: FSSpecPtr; rulesMask: LongInt;
  941.                      alias: AliasHandle; VAR aliasCount: Integer; 
  942.                      aliasList: FSSpecArrayPtr; VAR needsUpdate: Boolean;
  943.                      aliasFilterProcPtr: ProcPtr; yourDataPtr: UNIV Ptr) 
  944.                      : OSErr;
  945.  
  946. MatchAlias resolves the alias record specified by the alias parameter, following
  947. the rules specified by the rulesMask parameter, and returns a list of possible
  948. candidates in the structure specified by the aliasList parameter. MatchAlias
  949. places the number of candidates identified in the aliasCount parameter.
  950.  
  951. The fromFile parameter represents the starting point for a relative search. If
  952. you do not want MatchAlias to perform a relative search, set fromFile to NIL. If
  953. you want MatchAlias to perform a relative search, pass a pointer to a file
  954. system specification record that describes the starting point for the search.
  955.  
  956. The rulesMask parameter specifies a set of rules to guide the resolution. Pass
  957. the sum of all of the rules you want to invoke.
  958.  
  959.    Constant                        Description
  960.  
  961.    kARMsearch                 Perform a fast search for the alias target.
  962.  
  963.                                              If kARMsearchRelFirst is not set,
  964.                                              perform a direct search 
  965.                                              first, followed by a relative
  966.                                              search only if the fromFile 
  967.                                              parameter is not NIL and the list
  968.                                              of matches is not full.
  969.  
  970.    kARMsearchMore        Perform an exhaustive search for the alias target.
  971.  
  972.                                               On HFS volumes, the exhaustive
  973.                                               search uses the File 
  974.                                               Manager function PBCatSearch to
  975.                                               identify candidates with
  976.                                               matching creation date, type, and
  977.                                               creator. PBCatSearch is 
  978.                                               available only on HFS volumes and
  979.                                               only on systems 
  980.                                               running version 7.0 or later. On
  981.                                               MFS volumes or HFS 
  982.                                               volumes that do not support
  983.                                               PBCatSearch the exhaustive 
  984.                                               search makes a series of indexed
  985.                                               calls to File Manager 
  986.                                               functions, using the same search
  987.                                               criteria.
  988.  
  989.                                                If you set kARMsearchMore and one
  990.                                                or both of 
  991.                                                kARMsearch and
  992.                                                kARMsearchRelFirst, MatchAlias 
  993.                                                performs the fast search first.
  994.  
  995.    kARMsearchRelFirst     If kARMsearch is also set, perform a relative search
  996.    before
  997.                                                the direct search. (If kARMsearch
  998.                                                is also set and the target 
  999.                                                is found through the direct
  1000.                                                search, MatchAlias sets the 
  1001.                                                needsUpdate flag to TRUE.)
  1002.  
  1003.                                                If neither kARMsearch nor
  1004.                                                kARMsearchMore is set, 
  1005.                                                perform only a relative search.
  1006.  
  1007.                                                If kARMsearch is not set but
  1008.                                                kARMsearchMore is set, 
  1009.                                                perform a relative search
  1010.                                                followed by an exhaustive 
  1011.                                                search.
  1012.  
  1013.    kARMmountVol           Automatically try to mount the target’s volume if it
  1014.    is not
  1015.                                                mounted.
  1016.  
  1017.    kARMmultVols             Search all mounted volumes.
  1018.  
  1019.                                                The search begins with the volume
  1020.                                                on which the target 
  1021.                                                resided when the record was
  1022.                                                created.
  1023.  
  1024.                                                When you specify a fast search of
  1025.                                                all mounted volumes, 
  1026.                                                MatchAlias performs a formal fast
  1027.                                                search only on the 
  1028.                                                volume described in the alias
  1029.                                                record. On all other 
  1030.                                                volumes, it looks for the target
  1031.                                                by ID or by name in the 
  1032.                                                directory with the specified
  1033.                                                parent directory ID.
  1034.  
  1035.                                               When you specify an exhaustive
  1036.                                               search of multiple 
  1037.                                                volumes, MatchAlias performs the
  1038.                                                same search on all 
  1039.                                                volumes.
  1040.  
  1041.                                               When resolving an alias record
  1042.                                               created by  
  1043.                                               NewAliasMinimalFromFullpath,
  1044.                                               MatchAlias ignores this
  1045.                                               flag.
  1046.  
  1047.    kARMnoUI                    Stop if a search requires user interaction, such
  1048.    as a 
  1049.                                              password dialog box when mounting a
  1050.                                              remote volume.
  1051.  
  1052.                                              If user interaction is needed and
  1053.                                              kARMnoUI is in effect, 
  1054.                                              the search fails.
  1055.  
  1056. You must specify at least one of the first three parameters: kARMsearch,
  1057. kARMsearchMore, and kARMsearchRelFirst.
  1058.  
  1059. The alias parameter is a handle to the alias record to be resolved.
  1060.  
  1061. Your application can specify a maximum number of possible matches by setting the
  1062. aliasCount parameter. MatchAlias changes the aliasCount parameter to the actual
  1063. number of candidates identified. If MatchAlias finds the parent directory on the
  1064. correct volume but does not find the target, it sets the aliasCount parameter to
  1065. 1, puts the file system specification record for the target in the results list,
  1066. and returns fnfErr. The FSSpec record is valid, although the object it describes
  1067. does not exist. This information is intended as a “hint” that lets you explore
  1068. possible solutions to the resolution failure. You can, for example, use the
  1069. FSSpec record to create a replacement for a missing file with the File Manager
  1070. function FSpCreate.
  1071.  
  1072. The aliasList parameter points to the array that holds the results of the
  1073. search.
  1074.  
  1075. The needsUpdate flag is a signal to your application that the record might need
  1076. to be updated. After it identifies a target, MatchAlias compares some key
  1077. information about the target with the same information in the record. If the
  1078. information does not match, MatchAlias sets the needsUpdate flag to TRUE. The
  1079. key information is
  1080.  
  1081.    • the name of the target
  1082.  
  1083.    • the directory ID of the target’s parent
  1084.  
  1085.    • the file ID or directory ID of the target
  1086.  
  1087.    • the name and creation date of the volume on which the target resides
  1088.  
  1089. MatchAlias also sets the needsUpdate flag to TRUE if it identifies a list of
  1090. possible matches rather than a single match or if kARMsearchRelFirst is set but
  1091. the target is identified through either a direct search or an exhaustive search.
  1092. Otherwise, MatchAlias sets the needsUpdate flag to FALSE. MatchAlias always sets
  1093. the needsUpdate flag to FALSE when resolving an alias created by
  1094. NewAliasMinimal. If you want to update the alias record to reflect the final
  1095. results of the resolution, call UpdateAlias.
  1096.  
  1097. The aliasFilter parameter points to a filter function supplied by your
  1098. application. The Alias Manager executes this function each time it identifies a
  1099. possible match and after the search has continued for three seconds without  a
  1100. match. Your filter function returns a Boolean value that determines whether the
  1101. possible match is discarded (TRUE) or added to the list of possible targets
  1102. (FALSE). It can also terminate the search by setting the variable parameter
  1103. quitFlag. See “Filtering Possible Targets” later in the chapter for a
  1104. description of the filter function, which follows this syntax:
  1105.  
  1106.    FUNCTION MyMatchAliasFilter (cpbPtr: CInfoPBPtr;
  1107.                               VAR quitFlag: Boolean;
  1108.                               myDataPtr: Ptr): Boolean;
  1109.  
  1110. The yourDataPtr parameter can point to any data that your application might need
  1111. in the filter function. Use the myDataPtr parameter to pass global or local data
  1112. to your filter function.
  1113.  
  1114.    Result codes
  1115.           nsvErr                    –35        The volume is not mounted
  1116.           fnfErr                      –43         No target was found
  1117.           paramErr                –50        target, alias, or both are NIL, or
  1118.           the alias record is
  1119.                                                           corrupt
  1120.           usrCanceledErr    –128       The user cancelled the operation
  1121.  
  1122. You can use the GetAliasInfo function to get information from an alias record
  1123. without actually resolving the record.
  1124.  
  1125. FUNCTION GetAliasInfo (alias: AliasHandle; index: AliasInfoType;
  1126.                        VAR theString: Str63 ) : OSErr;
  1127.  
  1128. GetAliasInfo retrieves the information specified by the index parameter from the
  1129. record pointed to by the alias parameter and places it in the parameter
  1130. theString.
  1131.  
  1132. The alias parameter is a handle to the alias record to be read.
  1133.  
  1134. The index parameter specifies the kind of information to be retrieved. If index
  1135. is a positive integer, GetAliasInfo retrieves the parent directory that has the
  1136. same hierarchical level above the target as the index parameter (for example, an
  1137. index value of 2 returns the name of the parent directory of the target’s parent
  1138. directory). You can therefore assemble the names of the target and all of its
  1139. parent directories by making repeated calls to GetAliasInfo with incrementing
  1140. index values, starting with a value of 0. When index is greater than the number
  1141. of levels between the target and the root, GetAliasInfo returns an empty string.
  1142. You can also set the index parameter to one of these values:
  1143.  
  1144.    Constant               Value        Description
  1145.  
  1146.    asiZoneName         –3            If the record represents a target on an
  1147.    AppleShare 
  1148.                                                       volume, retrieve the
  1149.                                                       server’s zone name.
  1150.                                                       Otherwise, 
  1151.                                                       return an empty string.
  1152.  
  1153.    asiServerName       –2            If the record represents a target on an
  1154.    AppleShare 
  1155.                                                        volume, retrieve the
  1156.                                                        server name. Otherwise,
  1157.                                                        return
  1158.                                                        an empty string.
  1159.  
  1160.    asiVolumeName    –1            Return the name of the volume on which the
  1161.    target 
  1162.                                                         resides.
  1163.  
  1164.    asiAliasName            0            Return the name of the target.
  1165.  
  1166.    asiParentName          1            Return the name of the parent directory
  1167.    of the target 
  1168.                                                        of the record. If the
  1169.                                                        target is a volume,
  1170.                                                        return the 
  1171.                                                        volume name.
  1172.  
  1173. GetAliasInfo places the requested information in the parameter theString.
  1174.  
  1175. GetAliasInfo returns the information stored in the alias record, which might not
  1176. be current. To ensure that the information is current, you can resolve and
  1177. update the alias record before calling GetAliasInfo.
  1178.  
  1179. GetAliasInfo cannot provide all kinds of information on a minimal alias.
  1180.  
  1181.    Result codes
  1182.           paramErr         –50               alias, theString, or both are NIL;
  1183.           the index is less
  1184.                                                           than asiZoneName; or
  1185.                                                           the alias record is
  1186.                                                           corrupt
  1187. _______________________________________________________________________________
  1188.  
  1189. æKY Filtering…Possible…Targets
  1190. æC »Filtering Possible Targets                                           The Alias Manager
  1191. _______________________________________________________________________________
  1192.  
  1193. You can write your own filter function to examine possible targets identified by
  1194. the MatchAlias function. MatchAlias calls your filter function each time it
  1195. identifies a possible match and when three seconds have elapsed without a match.
  1196.  
  1197. The filter function takes three parameters and returns a Boolean value:
  1198.  
  1199. FUNCTION MyMatchAliasFilter (cpbPtr: CInfoPBPtr; VAR quitFlag: Boolean;    
  1200.                              myDataPtr: Ptr): Boolean;
  1201.  
  1202. The cpbPtr parameter points to the catalog information parameter block record
  1203. (as returned by the File Manager function PBGetCatInfo) of the possible match.
  1204. MatchAlias sets this parameter to NIL if it is calling your function to give it
  1205. the periodic chance to terminate the search. (Do not use this pointer without
  1206. checking for NIL.)
  1207.  
  1208. Your filter function sets the quitFlag parameter to terminate the search.
  1209.  
  1210. The myDataPtr parameter points to any customized data that your application
  1211. passed when it called MatchAlias. This parameter allows your filter function to
  1212. access any data that your application has set up on its own.
  1213.  
  1214. The Boolean return value determines whether the possible match is discarded
  1215. (TRUE) or added to the list of possible targets (FALSE).
  1216.  
  1217. _______________________________________________________________________________
  1218.  
  1219. æKY Summary…of…the…Alias…Manager…Volume…VI
  1220. æC »Summary of the Alias Manager Volume VI                               The Alias Manager
  1221. _______________________________________________________________________________
  1222.  
  1223. Click the arrow in the lower-right corner of this wondow to see the summary
  1224. sections of the constants, data types, and routines for the Alias Manager.
  1225. _______________________________________________________________________________
  1226.  
  1227. æKY Alias…Manager…Constants
  1228. æC »Alias Manager Constants                                              The Alias Manager
  1229. _______________________________________________________________________________
  1230.  
  1231. CONST
  1232.      rAliasType          =  'alis';  {alias record resource type}
  1233.  
  1234.      {rulesMask for MatchAlias}
  1235.      kARMmountVol        =  $0001;   {mount the volume automatically}
  1236.      kARMnoUI            =  $0002;   {suppress user interface}
  1237.      kARMmultVols        =  $0008;   {search on multiple volumes}
  1238.      kARMsearch          =  $0100;   {perform a fast search}
  1239.      kARMsearchMore      =  $0200;   {perform an exhaustive search}
  1240.      kARMsearchRelFirst  =  $0400;   {perform a relative search first}
  1241.  
  1242.      {index values for GetAliasInfo}
  1243.      asiZoneName         =     –3;   {get zone name}
  1244.      asiServerName       =     –2;   {get server name}
  1245.      asiVolumeName       =     –1;   {get volume name}
  1246.      asiAliasName        =      0;   {get target name}
  1247.      asiParentName       =      1;   {get parent directory name}
  1248. _______________________________________________________________________________
  1249.  
  1250. æKY Alias…Manager…Data…Types
  1251. æC »Alias Manager Data Types                                             The Alias Manager
  1252. _______________________________________________________________________________
  1253.  
  1254. TYPE  AliasHandle    =                ^AliasPtr;
  1255.       AliasPtr       =                ^AliasRecord;
  1256.  
  1257.       AliasRecord    =
  1258.       RECORD
  1259.          userType:   OSType;           {application’s signature}
  1260.          aliasSize:  Integer;          {size of record when created}
  1261.          {variable-length private data}
  1262.       END;
  1263.   
  1264.       AliasInfoType  =  Integer;       {alias record information type}
  1265.   
  1266.       AliasFilterProcPtr  =  ProcPtr;  {application-defined routine; }
  1267.                                        { see sample }
  1268.                                        { FUNCTION MyMatchAliasFilter}
  1269. _______________________________________________________________________________
  1270.  
  1271. æKY Alias…Manager…Routines…Summary
  1272. æC »Alias Manager Routines Summary                                       The Alias Manager
  1273. _______________________________________________________________________________
  1274.  
  1275. Creating and Updating Alias Records
  1276.  
  1277. FUNCTION NewAlias                     (fromFile: FSSpecPtr;
  1278.                                        target: FSSpec;
  1279.                                        VAR alias: AliasHandle) : OSErr;
  1280. FUNCTION NewAliasMinimal              (target: FSSpec;
  1281.                                        VAR alias: AliasHandle) : OSErr;
  1282. FUNCTION NewAliasMinimalFromFullpath  (fullpathLength: Integer;
  1283.                                        fullpath: Ptr; zoneName: Str32; 
  1284.                                        serverName: Str31;
  1285.                                        VAR alias: AliasHandle) : OSErr;
  1286. FUNCTION UpdateAlias                  (fromFile: FSSpecPtr;
  1287.                                        target: FSSpec; alias: AliasHandle; 
  1288.                                        VAR wasChanged: Boolean) : OSErr;
  1289.  
  1290.  
  1291. Resolving and Reading Alias Records
  1292.  
  1293. FUNCTION ResolveAlias                  (fromFile: FSSpecPtr;
  1294.                                         alias: AliasHandle;
  1295.                                         VAR target: FSSpec;
  1296.                                         VAR wasChanged: Boolean) : OSErr;
  1297.  
  1298. FUNCTION MatchAlias                    (fromFile: FSSpecPtr;
  1299.                                         rulesMask: LongInt;
  1300.                                         alias: AliasHandle;
  1301.                                         VAR aliasCount: Integer;
  1302.                                         aliasList: FSSpecArrayPtr;
  1303.                                         VAR needsUpdate: Boolean; 
  1304.                                         aliasFilterProcPtr: ProcPtr; 
  1305.                                         yourDataPtr: UNIV Ptr) : OSErr;
  1306.  
  1307. FUNCTION GetAliasInfo                  (alias: AliasHandle;
  1308.                                         index: AliasInfoType;
  1309.                                         VAR theString: Str63) : OSErr;
  1310. _______________________________________________________________________________
  1311.  
  1312. æKY Alias…Manager…Application-Defined…Routine
  1313. æC »Alias Manager Application-Defined Routine                            The Alias Manager
  1314. _______________________________________________________________________________
  1315.  
  1316. FUNCTION MyMatchAliasFilter                (cpbPtr: CInfoPBPtr;
  1317.                                             VAR quitFlag: Boolean;
  1318.                                             myDataPtr: Ptr): Boolean;
  1319. _______________________________________________________________________________
  1320.  
  1321. æKY Alias…Manager…Result…Codes
  1322. æC »Alias Manager Result Codes                                           The Alias Manager
  1323. _______________________________________________________________________________
  1324.  
  1325. nsvErr                       –35       The volume is not mounted
  1326. fnfErr                         –43       No target was found
  1327. paramErr                  –50       One or more parameters are NIL, or a handle
  1328. is corrupt
  1329. dirNFErr                –120       Parent directory not found
  1330. usrCanceledErr     –128       The user cancelled the operation
  1331. _______________________________________________________________________________
  1332.  
  1333. æKY Alias…Manager…Assembly-Language…Information
  1334. æC »Alias Manager Assembly-Language Information                          The Alias Manager
  1335. _______________________________________________________________________________
  1336.  
  1337. Alias Record Data Structure
  1338.  
  1339. userType            4 bytes            file type of target file
  1340. aliasSize             2 bytes            size of record in bytes
  1341. {variable-length private data}
  1342.  
  1343.  
  1344.  
  1345.  
  1346. _______________________________________________________________________________
  1347.  
  1348.  
  1349. æKY AppleDesktopBus
  1350. æC 
  1351. THE APPLE DESKTOP BUS
  1352. _______________________________________________________________________________
  1353.  
  1354. About…The…AppleDesktopBus…Chapter
  1355. About…the…Apple…Desktop…Bus
  1356. ADB…Manager…Routines
  1357. Writing…ADB…Device…Drivers
  1358. Summary…of…the…ADB
  1359. _______________________________________________________________________________
  1360.  
  1361.  
  1362.  
  1363. æKY About…The…AppleDesktopBus…Chapter
  1364. æC »ABOUT THIS CHAPTER                                        AppleDesktopBus
  1365. _______________________________________________________________________________
  1366.  
  1367. This chapter tells you how to accomplish low-level communication with peripheral
  1368. devices that are connected to the Apple Desktop Bus (ADB).
  1369.  
  1370. Reader’s guide:    The standard mouse and keyboard drivers automatically take
  1371.                    care of all required ADB access functions. When the user
  1372.                    manipulates the mouse or keyboard, the system calls the
  1373.                    appropriate driver and the application never uses the ADB
  1374.                    Manager. Hence you need the information in this chapter only
  1375.                    if you are writing a special driver, such as a driver for a
  1376.                    new user-input device.
  1377.  
  1378. The ADB is a simple local-area network that connects low-speed input-only devices to
  1379. the operating system. In the Macintosh II and Macintosh SE computers, the ADB is used
  1380. to communicate with one or more keyboards, the mouse, and other user input devices.
  1381.  
  1382. Keys located on multiple keyboards are distinguished by the keyboard event message,
  1383. as described in the Toolbox Event Manager chapter.
  1384.  
  1385. Note:  An ADB, using the same operating protocols, is also part of the
  1386.        Apple IIgs computer.
  1387.  
  1388. This chapter contains three principal sections:
  1389.  
  1390.   •  a description of the Apple Desktop Bus and how it works
  1391.   •  a description of the ADB Manager. This section of system ROM contains
  1392.      the routines that a driver must use to access devices connected to the ADB.
  1393.   •  a discussion of the special requirements for drivers that support
  1394.      devices connected to the ADB
  1395.  
  1396. You should already be familiar with
  1397.  
  1398.   •  the hardware interface to the Apple Desktop Bus, described in the
  1399.      Macintosh Family Hardware Reference
  1400.   •  events generated by ADB keyboard devices (described in the Toolbox
  1401.      Event Manager chapter) if your driver communicates with one or more
  1402.      keyboards
  1403.  
  1404. _______________________________________________________________________________
  1405.  
  1406.  
  1407. æKY About…the…Apple…Desktop…Bus
  1408. æC »ABOUT THE APPLE DESKTOP BUS                               AppleDesktopBus
  1409. _______________________________________________________________________________
  1410.  
  1411. The Apple Desktop Bus connects up to 16 low-speed input-only devices to the Macintosh
  1412. II or Macintosh SE computer. Each device can maintain up to four variable-size registers,
  1413. whose contents can be read from or written to by the ADB network. Each register may
  1414. contain from two to eight bytes. Two of the device registers have an assigned meaning
  1415. and a standardized format: register 0, used for interrupt information, and register
  1416. 3, containing the device’s identification number. The other two device registers have
  1417. no assigned meaning, and may have different meanings for read and write operations.
  1418.  
  1419. The system communicates with the Apple Desktop Bus through the system’s Versatile
  1420. Interface Adapter chip (VIA). The VIA is described in the Macintosh Hardware chapter.
  1421.  
  1422. Warning:  The ADB does not support connecting a device while the computer
  1423.           is running. The result may be to reinitialize all devices on the
  1424.           bus without informing the system.
  1425.  
  1426. The system always controls the bus. It issues commands to specific devices on the bus
  1427. and they respond by accepting data, sending data, or changing their configuration.
  1428. These commands are discussed below.
  1429.  
  1430. Note:  Devices connected to the ADB contain their own single-chip
  1431.        microprocessors, which handle both device routines and the
  1432.        ADB interface. If the system sends commands to a device with
  1433.        a duty cycle of more than 50%, the device’s microprocessor
  1434.        may become overloaded.
  1435.  
  1436. _______________________________________________________________________________
  1437.  
  1438. »Bus Commands
  1439.  
  1440. Each bus command consists of a byte that the system sends to a device connected to
  1441. the ADB. Applications may place bus commands on the network by calling the routine
  1442. ADBOp, discussed under “ADB Manager Routines” later in this chapter. There are four
  1443. bus commands; their bit layouts are shown in Figure 1.  All other bit layouts are
  1444. reserved.
  1445.  
  1446. •••Refer to Figure 1.•••
  1447.  
  1448. Figure 1–ADB Command Formats
  1449.  
  1450. The individual commands are discussed below.
  1451.  
  1452. Warning:  Values of the low bytes of the ADB command formats other than
  1453.           those shown in Figure 1 are reserved, and should not be used.
  1454.  
  1455. »SendReset
  1456.  
  1457. The SendReset command forces a hardware reset of all devices connected to the ADB.
  1458. Such a reset clears all pending device actions and places the devices in their startup
  1459. state. All devices are able to accept new ADB commands and user inputs immediately
  1460. thereafter. All devices ignore the high-order four bits of the SendReset command.
  1461.  
  1462. »Flush
  1463.  
  1464. The Flush command flushes data from the single device specified by the network address
  1465. in its high-order four bits. Network  addresses are discussed below, under “Device
  1466. Addressing”. It purges any pending user inputs and make the device ready to accept
  1467. new commands and input data.
  1468.  
  1469. »Listen
  1470.  
  1471. The Listen command is used to send instructions to devices connected to the ADB. It
  1472. transfers data from a buffer in system RAM to a register in the device specified by
  1473. the network address in its high-order four bits. The device register is specified by
  1474. the low-order two bits of the Listen command.
  1475.  
  1476. »Talk
  1477.  
  1478. The Talk command is used to fetch user inputs from devices connected to the ADB. It
  1479. is the complement of the Listen command. It transfers data from a register in the
  1480. device specified by the network address in its high-order four bits to a buffer in
  1481. system RAM. The device register is specified by the low-order two bits of the Talk
  1482. command.
  1483.  
  1484. _______________________________________________________________________________
  1485.  
  1486. »Device Registers
  1487.  
  1488. Each device connected to the ADB contains four registers, each of which may store
  1489. from two to eight bytes of data. Each register is identified by the value of the
  1490. low-order two bits in a Listen or Talk command. Registers 0 and 3 have dedicated
  1491. functions; registers 1 and 2 are used for purposes specific to each device, and need
  1492. not be present in a device.
  1493.  
  1494. Note:  ADB device registers are virtual registers; they need not be
  1495.        implemented physically.  The device firmware must only respond
  1496.        to register commands as if a register were present.
  1497.  
  1498. »Register 0
  1499.  
  1500. Device register 0 is reserved for input data. If the device has user-input data to be
  1501. fetched, it places the data in register 0 and requests service. It continues to
  1502. request service until the system retrieves its data.  The system responds to data-input
  1503. requests with the following polling sequence:
  1504.  
  1505.   •  It generates a Talk command for register 0 in each device connected
  1506.      to the ADB.
  1507.   •  If the device has data to send, it responds.  The system does not
  1508.      poll the next device until the data is exhausted.
  1509.   •  If the device has no data to send, or if its data is exhausted, the
  1510.      VIA generates an interrupt.  The system then polls the next device.
  1511.   •  This process continues until no devices request service.
  1512.  
  1513. »Register 3
  1514.  
  1515. Device register 3 is reserved for device identification data and operating flags.
  1516. Application programs may set this data with Listen commands and read it with Talk
  1517. commands. Register 3 stores 16 bits, divided into the fields shown in Figure 2.
  1518.  
  1519. •••Refer to Figure 2.•••
  1520.  
  1521. Figure 2–Format of Device Register 3
  1522.  
  1523. Except for commands that contain certain reserved device handler ID values
  1524. (listed below), every command to register 3 changes the entire register contents.
  1525. Hence to change part of the register, you should first fetch its current contents
  1526. with a Talk command and then send it an updated value with Listen. You can change
  1527. part of the contents of register 3 by using special device handler ID values, as
  1528. described below.
  1529.  
  1530. The device handler ID field indicates the device’s type. With certain devices, an
  1531. application can change the device’s mode of operation by sending it a new ID value.
  1532. If the device supports the new mode, it stores the new value in this field.
  1533.  
  1534. Warning:  You are assigned handler IDs by Apple Software Licensing, so
  1535.           they do not conflict with the values of other devices that may
  1536.           be connected to the ADB at the same time.
  1537.  
  1538. When certain reserved values are sent to the device handler ID field by a Listen
  1539. command, they are not stored in the field; instead, they cause specific device actions.
  1540. Hence these values cannot be used as device ID values. They are the following:
  1541.  
  1542.   Value  Action
  1543.  
  1544.   $00    Change bits 8–13 of register 3 to match the rest of the command;
  1545.          leave Device Handler ID value unchanged.
  1546.   $FD    Change Device Address to match bits 8–11 if the device activator
  1547.          has been depressed; leave Device Handler ID value and flags unchanged.
  1548.   $FE    Change Device Address to match bits 8–11 if the result produces no
  1549.          address duplication on the bus; leave Device Handler ID value and
  1550.          flags unchanged.
  1551.   $FF    Initiate device self-test. If self-test succeeds, leave register 3
  1552.          unchanged; if self-test fails, clear Device Handler ID field to $00.
  1553.  
  1554. Other Device Handler ID values may be stored in the field.
  1555.  
  1556. Note:  Device Handler ID values below $20 are reserved by Apple.
  1557.  
  1558. The Device Address field indicates the device’s location within the 16 possible
  1559. device locations of the ADB. An application may change its value with a Listen command.
  1560. When this field is interrogated with a Talk command, it returns a random value. This
  1561. helps you separate multiple devices that have the same ADB address; for further
  1562. information, see “Device Addressing”, below.
  1563.  
  1564. The Service Request Enable bit is set by the device to request an interrupt poll.
  1565.  
  1566. _______________________________________________________________________________
  1567.  
  1568. »Device Addressing
  1569.  
  1570. There are 16 possible direct addresses, $00–$0F, for devices connected to the ADB.
  1571. However, it is possible to connect more than one device to an address; this might
  1572. happen, for example, in a system with two alternate keyboards.
  1573.  
  1574. When several devices share a single ADB address, but there are free addresses available
  1575. in the net, the system will automatically reassign addresses until they are all
  1576. different. It will do this every time the ADB Manager is initialized or reinitialized.
  1577. To find out a device’s new address, use the calls GetIndADB or GetADBInfo, described
  1578. later in this chapter.
  1579.  
  1580. _______________________________________________________________________________
  1581.  
  1582. »Standard ADB Device Drivers
  1583.  
  1584. The Macintosh II and Macintosh SE systems contain two standard ADB drivers:
  1585.  
  1586.   •  the mouse driver, which supports the ADB mouse. The Apple mouse
  1587.      has an original ADB address of 3.
  1588.   •  the universal keyboard driver, which supports all Apple ADB keyboards.
  1589.      The Apple keyboard has an original ADB address of 2, with a Device
  1590.      Handler ID of 1 for the Macintosh II keyboard and 2 for the Apple
  1591.      Extended Keyboard.  These keyboards are described in the Toolbox
  1592.      Event Manager chapter. 
  1593.  
  1594. These drivers reside in the system ROM. In addition, ADB address 0 is reserved for
  1595. the ADB chip itself.  You can change the ADB addresses of the mouse or keyboard, as
  1596. described above under “Device Registers,” but Apple does not recommend doing so.
  1597.  
  1598. Assembly-language note:  The ADB address of the keyboard on which the
  1599.                          last-typed character was entered is now stored
  1600.                          in the global variable KbdLast. The type of the
  1601.                          keyboard on which the last-typed character was
  1602.                          entered is stored in the global variable KbdType.
  1603.                          The value of KbdType is the Device Handler ID
  1604.                          value in Register 3 of the device; values below
  1605.                          $20 are reserved by Apple.
  1606.  
  1607. The requirements for writing new ADB device drivers are discussed later in this
  1608. chapter.
  1609.  
  1610. _______________________________________________________________________________
  1611.  
  1612.  
  1613. æKY ADB…Manager…Routines
  1614. æC »ADB MANAGER ROUTINES                                      AppleDesktopBus
  1615. _______________________________________________________________________________
  1616.  
  1617. The ADB Manager consists of six routines located in the 256K ROM. You would use them
  1618. only if you needed to access bus devices directly or communicate with a special
  1619. device.
  1620.  
  1621. Some of these routines access and update information in the ADB device table, a
  1622. structure placed in the system heap by ROM code during system  startup. It lists for
  1623. each device the device’s type, its original ADB address, its current ADB address, the
  1624. address of the routine that services the device, and the address of the area in RAM
  1625. used for temporary data storage by its driver. The ADB device table is accessible
  1626. only through ADB Manager routines.
  1627.  
  1628. PROCEDURE ADBReInit;
  1629.  
  1630. Trap macro    _ADBReInit
  1631.  
  1632. ADBReInit reinitializes the entire Apple Desktop Bus. It clears the ADB device table
  1633. to zeros and places a SendReset command on the bus to reset all devices to their
  1634. original addresses. ADBReInit has no parameters.
  1635.  
  1636. Because it does not deallocate ADB resources on the system heap, ADBReInit should not
  1637. be used for routine bus initialization. Apple strongly recommends against adding
  1638. devices while the system is running; therefore, you should never call ADBReInit.
  1639.  
  1640. ADBReInit also calls a routine pointed to by the low memory global JADBProc
  1641. at the beginning and end of its execution.  You can insert your own
  1642. preprocessing/postprocessing routine by changing the value of JADBProc; ADBReInit
  1643. conditions it by setting D0 to 0 for preprocessing and to 1 for postprocessing.  Your
  1644. procedure must restore the value of D0 and branch to the original value of JADBProc
  1645. on exit.  JADBProc should be used to de-allocate memory used by the driver (see
  1646. MacDTS Sample Code “TbltDrvr” for an example), and then it should chain to the procedure
  1647. originally found in JADBProc.
  1648.  
  1649. The complete ADBReInit sequence is therefore the following:
  1650.  
  1651.   •  JSR to JADBProc with D0 set to 0
  1652.   •  reinitialize the Apple Desktop Bus
  1653.   •  clear the ADB device table
  1654.   •  JSR to JADBProc with D0 set to 1
  1655.  
  1656. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1657.                 commandNum: INTEGER) : OSErr;
  1658.  
  1659. Trap macro    _ADBOp
  1660.  
  1661. On entry:    A0:  pointer to parameter block
  1662.              D0:  commandNum (byte)
  1663.  
  1664. Parameter block
  1665.     -->    0    buffer      pointer
  1666.     -->    4    compRout    pointer
  1667.     -->    8    data        pointer
  1668.  
  1669. On exit:     D0:  result code (byte)
  1670.  
  1671. The completion routine pointed to by compRout will be passed the following parameters
  1672. on entry:
  1673.  
  1674.              D0:  commandNum (byte)
  1675.              A0:  pointer to buffer, data stored as a Pascal string (maximum
  1676.                   8 bytes data preceded by one length byte)
  1677.              A1:  pointer to completion routine (compRout)
  1678.              A2:  pointer to optional data area (data)
  1679.  
  1680. ADBOp transmits over the bus the command byte whose value is given by commandNum. The
  1681. structure of the command byte is given earlier in Figure 1. ADBOp executes only when
  1682. the ADB is otherwise idle; otherwise it is held in a command queue. It returns an
  1683. error if the command queue is full. The length of the data buffer pointed to by
  1684. buffer is contained in its first byte, like a Pascal string. The optional data area
  1685. pointed to by data is for local storage by the completion routine pointed to by
  1686. compRout. ADBop should be used sparingly; it is not intended for polling a device. 
  1687. The host automatically polls devices with data to deliver.
  1688.  
  1689. Result codes    noErr    No error
  1690.                 –1       Unsuccessful completion
  1691.  
  1692. FUNCTION CountADBs: INTEGER;
  1693.  
  1694. Trap macro    _CountADBs
  1695.  
  1696. On exit:    D0:  number of devices (byte)
  1697.  
  1698. CountADBs returns a value representing the number of devices connected to the ADB by
  1699. counting the number of entries in the device table. It has no arguments and returns
  1700. no error codes.
  1701.  
  1702. FUNCTION GetIndADB (VAR info: ADBDataBlock;
  1703.                     devTableIndex: INTEGER) : ADBAddress;
  1704.  
  1705. Trap macro    _GetIndADB
  1706.  
  1707. On entry:    A0:  pointer to parameter block
  1708.              D0:  entry index number; range = 1..CountADBs (byte)
  1709.  
  1710. Parameter block
  1711.     <--    0    device type                byte    (handler ID)
  1712.     <--    1    original ADB address       byte
  1713.     <--    2    service routine address    pointer (compRout)
  1714.     <--    6    data area address          pointer (data)
  1715.  
  1716. On exit:     D0:  positive value:  current ADB address (byte)
  1717.                   negative value:  error code (byte)
  1718.  
  1719. GetIndADB returns information from the ADB device table entry whose index number is
  1720. given by devTableIndex. ADBDataBlock has this form:
  1721.  
  1722. TYPE  ADBDataBlock =
  1723.              PACKED RECORD
  1724.                devType:         SignedByte; {device type (handler ID)}
  1725.                origADBAddr:     SignedByte; {original ADB address}
  1726.                dbServiceRtPtr:  Ptr;        {service routine address (compRout)}
  1727.                dbDataAreaAddr:  Ptr         {data area address (data)}
  1728.              END;
  1729.  
  1730. GetIndADB returns the current ADB address of the device. If it is unable to complete
  1731. execution successfully, GetIndADB returns a negative value.
  1732.  
  1733. FUNCTION GetADBInfo (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1734.  
  1735. Trap macro    _GetADBInfo
  1736.  
  1737. On entry:    A0:  pointer to parameter block
  1738.              D0:  ADB address of the device (byte)
  1739.  
  1740. Parameter block
  1741.     <--    0    device handler ID          byte
  1742.     <--    1    original ADB address       byte
  1743.     <--    2    service routine address    pointer (compRout)
  1744.     <--    6    data area address          pointer (data)
  1745.  
  1746. On exit:     D0:  result code (byte)
  1747.  
  1748. GetADBInfo returns information from the ADB device table entry of the device whose
  1749. ADB address is given by ABDAddr. The structure of ADBDataBlock is given above under
  1750. “GetIndADB”.
  1751.  
  1752. Result codes    noErr    No error
  1753.  
  1754. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1755.  
  1756. Trap macro    _SetADBInfo
  1757.  
  1758. On entry:    A0:  pointer to parameter block
  1759.              D0:  ADB address of the device (byte)
  1760.  
  1761. Parameter block
  1762.     -->    0    service routine address    pointer (compRout)
  1763.     -->    4    data area address          pointer (data)
  1764.  
  1765. On exit:     D0:  result code (byte)
  1766.  
  1767. SetADBInfo sets the service routine address and the data area address in the ADB
  1768. device table entry for the device whose ADB address is given by ABDAddr. ADBSetInfoBlock
  1769. has this form:
  1770.  
  1771. TYPE  ADBSetInfoBlock =
  1772.                RECORD
  1773.                  siServiceRtPtr:  Ptr;  {service routine address (compRout)}
  1774.                  siDataAreaAddr:  Ptr   {data area address (data)}
  1775.                END;
  1776.  
  1777. Result codes    noErr    No error
  1778.  
  1779. Warning:  You should send a Flush command to the device after calling it
  1780.           with SetADBInfo, to prevent it sending old data to the new data
  1781.           area address.
  1782.  
  1783. _______________________________________________________________________________
  1784.  
  1785.  
  1786. æKY Writing…ADB…Device…Drivers
  1787. æC »WRITING ADB DEVICE DRIVERS                                AppleDesktopBus
  1788. _______________________________________________________________________________
  1789.  
  1790. Drivers for devices connected to the ADB have the following special requirements:
  1791.  
  1792.   •  Each ADB device driver must reside in a resource of type 'ADBS'.
  1793.      (An example 'ADBS' resource is available in MacDTS Sample Code
  1794.      “TbltDrvr.”) This type has two sections: initialization and driver code.
  1795.   •  The initialization section of each ADB device driver must support the
  1796.      installation procedure described below.
  1797.  
  1798. When the system calls an ADB device driver, it passes it the following values:
  1799.  
  1800.   •  Register A0 points to the data buffer, which is formatted as a
  1801.      Pascal string (buffer).
  1802.   •  Register A1 points to the driver’s completion routine (compRout).
  1803.   •  Register A2 points to the optional data area (data).
  1804.   •  Register D0 contains the ADB command that resulted in the driver
  1805.      being called (commandNum).
  1806.  
  1807. The ADB driver should handle the ADB command passed to it and store any resulting
  1808. input data by an appropriate action, such as by posting an event or moving the cursor.
  1809.  
  1810. Note:  Events posted from keyboards connected to the ADB now have an
  1811.        expanded structure. For more information, see the Toolbox Event
  1812.        Manager chapter.
  1813.  
  1814. _______________________________________________________________________________
  1815.  
  1816. »Installing an ADB Driver
  1817.  
  1818. The Start Manager (described in this volume) finds all the ADB devices connected to
  1819. the system and places their device types and ADB addresses in the ADB device table.
  1820. It then calls the initialization section of each ADB device driver by executing the
  1821. initialization code in its 'ADBS' resource.
  1822.  
  1823. As a minimum, the initialization section of each ADB device driver must do the following:
  1824.  
  1825.   •  The driver must allocate all the memory required by the driver code
  1826.      in one or more nonrelocatable blocks in the system heap area.
  1827.   •  The driver must install its own preprocessing/postprocessing routine
  1828.      (if any) as described above under “ADBReInit”.
  1829.   •  Finally, the driver must initialize the service routine address and
  1830.      data area address of its entry in the ADB device table, using SetADBInfo.
  1831.  
  1832. _______________________________________________________________________________
  1833.  
  1834.  
  1835. æKY Summary…of…the…ADB
  1836. æC »SUMMARY OF THE ADB MANAGER                                AppleDesktopBus
  1837. _______________________________________________________________________________
  1838.  
  1839. Data Types
  1840.  
  1841. TYPE
  1842.   ADBDataBlock =
  1843.          PACKED RECORD
  1844.            devType:         SignedByte;  {Handler ID}
  1845.            origADBAddr:     SignedByte;  {original ADB address}
  1846.            dbServiceRtPtr:  Ptr;         {service routine address (compRout)}
  1847.            dbDataAreaAddr:  Ptr          {data area address (area)}
  1848.          END;
  1849.  
  1850.   ADBSetInfoBlock =
  1851.            RECORD
  1852.              siServiceRtPtr:  Ptr;  {service routine address}
  1853.              siDataAreaAddr:  Ptr   {data area address}
  1854.            END;
  1855.  
  1856. _______________________________________________________________________________
  1857.  
  1858. Routines
  1859.  
  1860. Initializing the ADB Manager
  1861.  
  1862. PROCEDURE ADBReInit;
  1863.  
  1864. Communicating Through the ADB
  1865.  
  1866. FUNCTION ADBOp (data: Ptr; compRout: ProcPtr; buffer: Ptr;
  1867.                 commandNum: INTEGER) : OSErr;
  1868.  
  1869. Getting ADB Device Information
  1870.  
  1871. FUNCTION CountADBs:  INTEGER;
  1872. FUNCTION GetIndADB   (VAR info: ADBDataBlock;
  1873.                       devTableIndex: INTEGER) : ADBAddress;
  1874. FUNCTION GetADBInfo  (VAR info: ADBDataBlock; ADBAddr: ADBAddress) : OsErr;
  1875.  
  1876. Setting ADB Device Information
  1877.  
  1878. FUNCTION SetADBInfo (VAR info: ADBSetInfoBlock; ADBAddr: ADBAddress) : OsErr;
  1879.  
  1880. _______________________________________________________________________________
  1881.  
  1882. Assembly-Language Information
  1883.  
  1884. Variables
  1885.  
  1886. JADBProc    Pointer to ADBReInit preprocessing/postprocessing routine
  1887. KbdLast     ADB address of the keyboard last used (byte)
  1888. KbdType     Keyboard type of the keyboard last used (byte)
  1889.  
  1890. Routines
  1891.  
  1892. Trap macro     On entry                               On Exit
  1893.  
  1894. _ADBReInit
  1895.  
  1896. _ADBOp         A0:  pointer to parameter block        D0:  result code (byte)
  1897.                     buffer (pointer)
  1898.                     compRout (pointer)
  1899.                     data (pointer)
  1900.                D0:  commandNum (byte)
  1901.  
  1902. _CountADBs                                            D0:  result code (byte)
  1903.  
  1904. _GetIndADB     A0:  pointer to parameter block        D0:  positive value:
  1905.                     device type (byte)                       current ADB
  1906.                     original ADB address (byte)              address (byte)
  1907.                     service routine address (pointer)        negative value:
  1908.                     data area address (pointer)              error code (byte)
  1909.                D0:  entry index number;
  1910.                     range = 1..CountADBs (byte)
  1911.  
  1912. _GetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1913.                     device handler ID (byte)           
  1914.                     original ADB address (byte)   
  1915.                     service routine address (pointer)   
  1916.                     data area address (pointer)
  1917.                D0:  current ADB address of the device (byte)
  1918.  
  1919. _SetADBInfo    A0:  pointer to parameter block        D0:  result code (byte)
  1920.                     service routine address (pointer)   
  1921.                     data area address (pointer)
  1922.                D0:  current ADB address of the device (byte)
  1923.  
  1924. Further Reference:
  1925. _______________________________________________________________________________
  1926. Toolbox Event Manager
  1927. Technical Note #143, Don’t Call ADBReInit on the SE with System 4.1
  1928. Technical Note #160, Key Mapping
  1929. Technical Note #206, Space Aliens Ate My Mouse
  1930. “Macintosh Family Hardware Reference”
  1931.  
  1932.  
  1933. æKY AppleEventManager
  1934. æC 
  1935. _______________________________________________________________________________
  1936.  
  1937. THE APPLE EVENT MANAGER
  1938. _______________________________________________________________________________
  1939.  
  1940. About…the…Apple…Event…Manager…Chapter…Volume…VI
  1941. About…the…Apple…Event…Manager…Volume…VI
  1942. Introduction…to…Apple…Events…Volume…VI
  1943.     Types…of…Apple…Events
  1944.     Components…of…Apple…Events
  1945.     Data…Structures…Within…Apple…Events
  1946.     Responding…to…Apple…Events
  1947.     Requesting…Services…Through…Apple…Events
  1948. Using…the…Apple…Event…Manager…Volume…VI
  1949.     Accepting…an…Apple…Event
  1950.     Installing…Entries…Into…the…Apple…Event…Dispatch…Tables
  1951.     Handling…the…Required…Apple…Events
  1952.         Required…Apple…Events
  1953.         Handling…the…Open…Application…Event
  1954.         Handling…the…Open…Documents…Event
  1955.         Handling…the…Print…Documents…Event
  1956.         Handling…the…Quit…Application…Event
  1957.         Handling…Apple…Events…Sent…by…the…Edition…Manager
  1958.         Handling…the…Create…Publisher…Event
  1959.     Getting…Data…out…of…an…Apple…Event
  1960.         Getting…Data…out…of…a…Parameter
  1961.         Getting…Data…out…of…an…Attribute
  1962.         Getting…Data…out…of…a…Descriptor…List
  1963.     Writing…Apple…Event…Handlers
  1964.     Replying…to…an…Apple…Event
  1965.     Disposing…of…Apple…Event…Data…Structures
  1966.     Interacting…With…the…User
  1967.     Creating…an…Apple…Event
  1968.         Adding…Parameters…to…an…Apple…Event
  1969.         Specifying…a…Target…Address
  1970.     Sending…an…Apple…Event
  1971.     Dealing…With…Timeouts
  1972.     Writing…an…Idle…Function
  1973.     Writing…a…Reply…Filter…Function
  1974.     Writing…and…Installing…Coercion…Handlers
  1975.     The…Application…Died…Event
  1976. Apple…Event…Manager…Routines…Volume…VI
  1977.     Creating…and…Managing…the…Apple…Event…Dispatch…Tables
  1978.     Dispatching…Apple…Events
  1979.     Getting…Parameters…and…Attributes…From…Apple…Events
  1980.     Counting…the…Items…in…Descriptor…Lists
  1981.     Getting…Items…From…Descriptor…Lists
  1982.     Getting…Data…From…AE…Records
  1983.     Requesting…User…Interaction
  1984.     Requesting…More…Time…to…Respond…to…Apple…Events
  1985.     Suspending…and…Resuming…Apple…Event…Handling
  1986.     Creating…Apple…Events
  1987.     Creating…and…Duplicating…Descriptor…Records
  1988.     Creating…Descriptor…Lists…and…AE…Records
  1989.     Adding…Items…to…Descriptor…Lists
  1990.     Adding…Data…to…AE…Records
  1991.     Adding…Parameters…and…Attributes…to…Apple…Events
  1992.     Sending…Apple…Events
  1993.     Getting…the…Sizes…and…Descriptor…Types…of…Descriptor…Records
  1994.     Deleting…Descriptor…Records
  1995.     Deallocating…Memory…for…Descriptor…Records
  1996.     Coercing…Descriptor…Types
  1997.     Creating…and…Managing…the…Coercion…Handler…Tables
  1998.     Creating…and…Managing…the…Special…Handler…Tables
  1999. Summary…of…the…Apple…Events…Manager…Volume…VI
  2000.     Apple…Events…Manager…Constants
  2001.     Apple…Events…Manager…Data…Types
  2002.     Apple…Events…Manager…Routines…Summary
  2003.     Apple…Events…Manager…Result…Codes
  2004.     Apple…Events…Manager…Assembly-Language…Information
  2005. _______________________________________________________________________________
  2006.  
  2007.  
  2008.  
  2009. æKY About…the…Apple…Event…Manager…Chapter…Volume…VI
  2010. æC »About the Apple Event Manager Chapter Volume VI                The Apple Event Manager
  2011. _______________________________________________________________________________
  2012.  
  2013. This chapter describes Apple® events and how your application can use the Apple
  2014. Event Manager to receive and process the required set of Apple events sent by
  2015. the Finder™. This chapter also describes how to use the Apple Event Manager to
  2016. send Apple events to other applications and how to process Apple events received
  2017. from other applications.
  2018.  
  2019. As explained in the Event Manager chapter in this volume, the Event Manager in
  2020. system software version 7.0 introduces high-level events, along with a number of
  2021. new Event Manager routines that let applications communicate with each other by
  2022. sending high-level events. Using Event Manager routines, your application can
  2023. create and process its own high-level events.
  2024.  
  2025. However, effective interapplication communication requires that applications
  2026. agree on a standard set of conventions—a common vocabulary. To provide such a
  2027. standard, Apple Computer, Inc., has defined a protocol called the Apple Event
  2028. Interprocess Messaging Protocol (AEIMP). High-level events that adhere to this
  2029. protocol are called Apple events.  You can help ensure effective communication
  2030. with other applications by using this protocol..
  2031.  
  2032. System software uses Apple events to communicate information to your
  2033. application; you should support the required set of Apple events sent by the
  2034. Finder to your application. In addition, you can support Apple events that are
  2035. common to many applications. Using the routines of the Apple Event Manager, you
  2036. can use Apple events to communicate with other applications in a standard way.
  2037. Using Apple events to ensure better cooperation between your application and
  2038. other applications helps users to get the most out of any one application or to
  2039. use the best features from many applications—in effect, combining the features
  2040. of many applications to achieve the desired result.
  2041.  
  2042. By following the standards specified by AEIMP, you can also define your own
  2043. Apple events. You can choose to publish these so that other applications can use
  2044. them, or you may choose to keep them unpublished for exclusive use by your own
  2045. applications.
  2046.  
  2047. The Apple Event Manager is available only in system software version 7.0. To
  2048. determine whether the Apple Event Manager is available, use the Gestalt function
  2049. described in the Compatibility Guidelines chapter of this volume.
  2050.  
  2051. The interapplication communications architecture of system software version 7.0
  2052. consists of three main components: the Apple Event Manager, the Event Manager,
  2053. and the Program-to-Program Communications (PPC) Toolbox. See the Introduction to
  2054. the System Software Version 7.0 Environment chapter in this volume for an
  2055. overview of the relationships among these components. If you intend to use
  2056. high-level events that do not rely on AEIMP, read the Event Manager chapter of
  2057. this volume. This chapter describes the information you need to know to support
  2058. Apple events in your application. To allow your application to send Apple events
  2059. to applications on remote computers, you may wish to use the PPCBrowser
  2060. function, which is described in the Program-to-Program Communications Toolbox
  2061. chapter of this volume.
  2062.  
  2063. While the Apple events used by the Edition Manager are discussed in this
  2064. chapter, you must refer to the Edition Manager chapter of this volume for a full
  2065. discussion of how to implement the Edition Manager’s publish and subscribe
  2066. features.
  2067.  
  2068. For descriptions of all publicly available Apple events, see the Apple Event
  2069. Registry,  available from Macintosh® Developer Technical Support.
  2070.  
  2071. _______________________________________________________________________________
  2072.  
  2073. æKY About…the…Apple…Event…Manager…Volume…VI
  2074. æC »About the Apple Event Manager Volume VI                        The Apple Event Manager
  2075. _______________________________________________________________________________
  2076.  
  2077. Apple events provide your application with a standard mechanism for
  2078. communicating with other applications. You can use Apple events and the Apple
  2079. Event Manager to
  2080.  
  2081.   • respond to the required Apple events (Open Application, Open Documents,
  2082.      Print Documents, and Quit Application) that are sent by the Finder
  2083.  
  2084.   • respond to the Apple events sent by the Edition Manager and allow users to
  2085.      share data among documents created by multiple applications
  2086.  
  2087.   • provide services to other applications
  2088.  
  2089.   • request services from other applications
  2090.  
  2091. By supporting the required Apple events, your application can take advantage of
  2092. the more reliable launch and termination mechanisms built into system software
  2093. version 7.0. You can also take advantage of the services provided by the Edition
  2094. Manager by responding to the Apple events sent by the Edition Manager. These and
  2095. additional core Apple events can be used by nearly all applications to
  2096. communicate with system software or with other applications.
  2097.  
  2098. You can also support functional-area Apple events related to your application in
  2099. order to provide services to other applications or to request services from
  2100. other applications. Finally, if your application defines Apple events for all
  2101. the actions that a user can perform, you can record user actions by generating
  2102. the corresponding Apple event for each action, saving a copy of the Apple event,
  2103. and then sending the Apple event to your own application for handling. Apple
  2104. events that are recorded in this way can later be played back to automate tasks
  2105. previously performed by the user.
  2106.  
  2107. To support Apple events in your application, you must
  2108.  
  2109.   • decide which Apple events (in addition to the required ones) to support
  2110.  
  2111.   • set bits in the 'SIZE' resource to indicate that your application supports 
  2112.      high-level events
  2113.  
  2114.   • create an Apple event dispatch table
  2115.  
  2116.   • include code to handle high-level events in your main event loop
  2117.  
  2118.   • handle the Apple events your application receives and wishes to support
  2119.  
  2120.   • create the Apple events you wish your application to generate
  2121.  
  2122. This chapter begins with an introduction to Apple events and then describes
  2123.  
  2124.   • the required Apple events that your application must support to be
  2125.   7.0-friendly
  2126.  
  2127.   • how to use the Apple Event Manager to send and process Apple events
  2128. _______________________________________________________________________________
  2129.  
  2130. æKY Introduction…to…Apple…Events…Volume…VI
  2131. æC »Introduction to Apple Events Volume VI                         The Apple Event Manager
  2132. _______________________________________________________________________________
  2133.  
  2134. Applications typically use Apple events to request services from and provide
  2135. services to other applications. For example, the Open Documents event, sent by
  2136. the Finder, requests that your application open specified documents. When your
  2137. application supports this Apple event, it should respond by opening those
  2138. documents in the manner that your application normally opens documents.
  2139.  
  2140. A transaction involving Apple events is initiated by a client application, which
  2141. sends an Apple event to request a service (for example, printing a list of
  2142. files, spell-checking a list of words, or performing a numerical calculation).
  2143. The application providing the service is called a server application. These
  2144. applications can reside on the same local computer or on remote computers
  2145. connected to a network.
  2146.  
  2147. Figure 6-1 shows a common Apple event, the Open Documents event. You see that
  2148. the Finder application is the client; it requests that the SurfWriter
  2149. application open the documents named Dec. Invoice and Nov. Invoice. The
  2150. SurfWriter application responds to the Finder’s request by opening windows
  2151. containing the specified documents.
  2152.  
  2153. ¿ Figure 6-1   An Open Documents event ø 
  2154.  
  2155. The Finder is also the source application of the Open Documents event. A source
  2156. application is one that sends an Apple event to another application or to
  2157. itself. In Figure 6-1, the SurfWriter application is the target application of
  2158. the event. The target application is the one addressed to receive the Apple
  2159. event. The terms client application  and source application  are not always
  2160. synonymous, nor are the terms server application  and target application.
  2161. Typically, an Apple event client sends an Apple event requesting a service from
  2162. an Apple event server; in this case, the server is the target application of the
  2163. Apple event. The Apple event server may send back a different Apple event as a
  2164. response—in which case, the client becomes the target of the responding Apple
  2165. event.
  2166.  
  2167. _______________________________________________________________________________
  2168.  
  2169. æKY Types…of…Apple…Events
  2170. æC »Types of Apple Events                                          The Apple Event Manager
  2171. _______________________________________________________________________________
  2172.  
  2173. Apple events fall into one of several broad categories.
  2174.  
  2175.   • Required Apple events consist of four core Apple events that the Finder
  2176.   sends
  2177.      to applications. These events are called Open Documents, Open Application,
  2178.      Print Documents, and Quit Application. They are a subset of the core Apple
  2179.      events and are described in detail later in this chapter.
  2180.  
  2181.   • Core Apple events are used by nearly all applications to communicate. The
  2182.   suite
  2183.      of core Apple events is described in the Apple Event Registry;  Apple
  2184.      recommends that all applications support the core Apple events.
  2185.  
  2186.   • Functional-area Apple events are supported by applications with related
  2187.      features. Apple events related to text manipulation for word-processing
  2188.      applications and Apple events related to graphics manipulation for drawing
  2189.      applications are examples of functional-area Apple events. Functional-area
  2190.      Apple events are defined by Apple in consultation with interested
  2191.      developers
  2192.      and are published in the Apple Event Registry. Apple recommends that all
  2193.      developers support functional-area Apple events appropriate for their types
  2194.      of
  2195.      applications.
  2196.  
  2197.   • Custom Apple events are defined by a developer for use by the developer’s
  2198.   own
  2199.      applications. You should register all of your custom Apple events with
  2200.      Macintosh Developer Technical Support. You can choose to publish your Apple
  2201.      events in the Apple Event Registry  so that other applications can share
  2202.      them, or
  2203.      you may choose to keep them unpublished for exclusive use by your own
  2204.      applications.
  2205. _______________________________________________________________________________
  2206.  
  2207. æKY Components…of…Apple…Events
  2208. æC »Components of Apple Events                                     The Apple Event Manager
  2209. _______________________________________________________________________________
  2210.  
  2211. An Apple event consists of attributes (which identify the Apple event and denote
  2212. its task) and, often, parameters (which contain data to be used by the target
  2213. application). An application uses the Apple Event Manager to create an Apple
  2214. event. Using arguments you pass to the AECreateAppleEvent function and to other
  2215. Apple Event Manager routines, the Apple Event Manager constructs the necessary
  2216. data structures containing attributes and parameters and converts these
  2217. structures into an Apple event. Applications must use the Apple Event Manager’s
  2218. AESend function to transmit the Apple event. After receiving an Apple event,
  2219. applications must use Apple Event Manager routines to extract the attributes and
  2220. parameters of the event.
  2221.  
  2222. Attributes are a fundamental component of Apple events. Apple event attributes
  2223. are records that identify the event class, event ID, target application, and
  2224. other characteristics of an Apple event. Taken together, the attributes of an
  2225. Apple event denote the task to be performed on any data specified in the Apple
  2226. event’s parameters. You do not have any direct way to access the data stored in
  2227. these records. You must use Apple Event Manager routines to extract or specify
  2228. the attributes.
  2229.  
  2230. An Apple event parameter is a record containing data that the target application
  2231. uses. Unlike Apple event attributes (which contain information that can be used
  2232. by both the Apple Event Manager and the target application), Apple event
  2233. parameters contain data used only by the target application. For example, an
  2234. attribute like the event ID is used by the Apple Event Manager to call a handler
  2235. from the server application’s dispatch table, and the server application must
  2236. have a handler to process the event identified by that attribute. By comparison,
  2237. the list of documents contained in a parameter to an Open Documents event is
  2238. used only by the server application. As with attributes, you do not have any
  2239. direct way to access the data structure of a parameter. You have to use Apple
  2240. Event Manager functions to extract or put data into parameters.
  2241.  
  2242. Note that Apple event parameters are different from the parameters of Apple
  2243. Event Manager functions. Apple event parameters are records private to the Apple
  2244. Event Manager; function parameters are arguments you pass to the function or
  2245. that the function returns to you. You typically specify the Apple event
  2246. parameters (as well as the attributes) in parameters to Apple Event Manager
  2247. functions. For example, the AEGetParamPtr function uses a buffer to return the
  2248. data contained in an Apple event parameter. You specify which Apple event
  2249. parameter in one of the parameters of the AEGetParamPtr function.
  2250.  
  2251. Apple events are identified by their event class and event ID attributes. The
  2252. event class is the attribute that identifies a group of related Apple events.
  2253. The event class appears in the message field of the event record for an Apple
  2254. event. For example, the four required Apple events (in fact, all core Apple
  2255. events) have the value 'aevt' in the message fields of their event records. The
  2256. value 'aevt' can also be represented by the kCoreEventClass constant. Several
  2257. event classes are shown here.
  2258.  
  2259.    Event class                            Value        Description
  2260.  
  2261.    kCoreEventClass                 'aevt'        A core Apple event
  2262.    kAEFinderEvents               'FNDR'    An event that the Finder accepts
  2263.    kSectionEventMsgClass    'sect'         An event sent by the Edition Manager
  2264.  
  2265. The event ID is the attribute that identifies the particular Apple event within
  2266. its event class. In conjunction with the event class, the event ID uniquely
  2267. identifies the Apple event and communicates what action the Apple event should
  2268. perform. (The event IDs appear in the where field of the event record for an
  2269. Apple event.) For example, the event ID of an Open Documents event has the value
  2270. 'odoc' (which can also be represented by the kAEOpenDocuments constant). The
  2271. kCoreEventClass constant in combination with the kAEOpenDocuments constant
  2272. identifies the Open Documents event to the Apple Event Manager.
  2273.  
  2274. Shown here are the event IDs for the four required Apple events.
  2275.  
  2276.    Event ID                             Value        Description
  2277.  
  2278.    kAEOpenApplication      'oapp'       Open your application
  2279.    kAEOpenDocuments       'odoc'       Open documents
  2280.    kAEPrintDocuments        'pdoc'       Print documents
  2281.    kAEQuitApplication        'quit'         Quit your application
  2282.  
  2283. The target application’s address is another required attribute. As previously
  2284. described, the target application is the one addressed to receive the Apple
  2285. event. Your application can send an Apple event to itself or to another
  2286. application (on the same computer or on a remote computer connected to the
  2287. network).
  2288.  
  2289. As with attributes, there are various types of Apple event parameters. A direct
  2290. parameter contains the data to be acted upon by the server application. For
  2291. example, a list of documents is contained in the direct parameter of the Print
  2292. Documents event. Direct parameters are usually required parameters—parameters
  2293. that the server application needs in order to carry out the task denoted by the
  2294. Apple event. Some Apple events also take additional parameters, which the server
  2295. application uses in addition to the data specified in the direct parameter. For
  2296. example, an Apple event for arithmetic operations may include additional
  2297. parameters that specify operands in an equation. Additional parameters may be
  2298. required or optional.
  2299.  
  2300. An optional parameter is a supplemental parameter that also can be used to
  2301. specify data to the server application. Optional parameters need not be included
  2302. in an Apple event; default values for optional parameters are part of the event
  2303. definition. The server application that handles the event must supply default
  2304. values if the optional parameters are omitted.
  2305.  
  2306. Figure 6-2 shows in greater detail the components of the Open Documents event
  2307. that was introduced in Figure 6-1.
  2308.  
  2309. ¿ Figure 6-2   Major components of an Open Documents event ø 
  2310.  
  2311. To process the information contained in the Open Documents event, the SurfWriter
  2312. application uses the AEProcessAppleEvent function. The AEProcessAppleEvent
  2313. function provides an easy way for your application to identify the event class
  2314. and event ID of the Apple event and to direct the Apple Event Manager to call
  2315. the code in your program that handles the Apple event.
  2316. _______________________________________________________________________________
  2317.  
  2318. æKY Data…Structures…Within…Apple…Events
  2319. æC »Data Structures Within Apple Events                            The Apple Event Manager
  2320. _______________________________________________________________________________
  2321.  
  2322. Applications must use Apple Event Manager functions to create and send an Apple
  2323. event. The Apple Event Manager constructs its own internal data structures to
  2324. contain the information in an Apple event. To gain access to this data, the
  2325. target application also must use Apple Event Manager functions. Neither the
  2326. sender nor the receiver of an Apple event can directly manipulate the data
  2327. inside an Apple event; each must rely on Apple Event Manager functions to do so.
  2328. This section describes the data structures that the Apple Event Manager uses to
  2329. create and to process Apple events.
  2330.  
  2331. Descriptor records are the fundamental structures from which Apple events are
  2332. constructed. A descriptor record is a data structure of type AEDesc; it consists
  2333. of a handle to data and a descriptor type that identifies the type of the data
  2334. referred to by the handle.
  2335.  
  2336. TYPE AEDesc = 
  2337.      RECORD
  2338.         descriptorType:   DescType;   {type of data being passed}
  2339.         dataHandle:       Handle      {handle to data being passed}
  2340. END;
  2341.  
  2342. The data referred to by the dataHandle field in the descriptor record is private
  2343. to the Apple Event Manager. You can supply or extract this data only by using
  2344. Apple Event Manager routines.
  2345.  
  2346. The descriptor type is a structure of type DescType, which in turn is of data
  2347. type ResType—that is, a four-character string. Constants are usually used in
  2348. place of these four-character strings when referring to descriptor types.
  2349. Descriptor types represent various data types. Here is a list of descriptor type
  2350. constants, their values, and the types of data they represent.
  2351.  
  2352.    Descriptor type                 Value       Description
  2353.  
  2354.    typeBoolean                      'bool'        Boolean value
  2355.    typeChar                            'TEXT'      Unterminated string
  2356.    typeSMInt                         'shor'        16-bit integer
  2357.    typeInteger                        'long'        32-bit integer
  2358.    typeSMFloat                      'sing';       SANE Single
  2359.    typeFloat                            'doub';      SANE Double
  2360.    typeLongInteger               'long'        32-bit integer
  2361.    typeShortInteger              'shor'        16-bit integer
  2362.    typeLongFloat                   'doub'       SANE Double
  2363.    typeShortFloat                  'sing'         SANE Single
  2364.    typeExtended                     'exte'         SANE Extended
  2365.    typeComp                           'comp'      SANE Comp
  2366.    typeMagnitude                  'magn'      Unsigned 32-bit integer
  2367.    typeAEList                          'list'           List of descriptor
  2368.    records
  2369.    typeAERecord                    'reco'         List of keyword-specified
  2370.    descriptor records
  2371.    typeAppleEvent                 'aevt'        Apple event record
  2372.    typeTrue                              'true'         TRUE Boolean value
  2373.    typeFalse                              'fals'          FALSE Boolean value
  2374.    typeAlias                              'alis'          Alias record
  2375.    typeEnumerated                'enum'      Enumerated data
  2376.    typeType                              'type'          Four-character code for
  2377.    event class or event
  2378.                                                                       ID
  2379.    typeAppParameters           'appa'        Process Manager launch parameters
  2380.    typeProperty                        'prop'        Apple event property
  2381.    typeFSS                                 'fss '           File system
  2382.    specification
  2383.    typeKeyword                       'keyw'       Apple event keyword
  2384.    typeSectionH                       'sect'         Handle to a section record
  2385.    typeTemporaryID               'tid '          Temporary ID
  2386.    typeWildCard                      '****'        Matches any type
  2387.    typeApplSignature             'sign'        Application signature
  2388.    typeSessionID                      'ssid'         Session ID
  2389.    typeTargetID                        'targ'         Target ID record
  2390.    typeProcessSerialNumber  'psn '       Process serial number
  2391.    typeNull                               'null'         NULL or nonexistent
  2392.    data
  2393.  
  2394. Figure 6-3 illustrates a descriptor record with a descriptor type of typeType,
  2395. which specifies that the data in the descriptor record must consist of a
  2396. four-character code. The data in this particular descriptor record is specified
  2397. by the constant kCoreEventClass, whose value is 'aevt'.
  2398.  
  2399. ¿ Figure 6-3   A descriptor record with event class data ø 
  2400.  
  2401. A descriptor record that contains the address of the target or source of an
  2402. Apple event is called  an address descriptor record.
  2403.  
  2404.    TYPE  AEAddressDesc = AEDesc;              {address descriptor record}
  2405.  
  2406. As you will see later, the address can be specified as an application signature,
  2407. a process serial number, a session ID, a target ID record, or a data type that
  2408. you define.
  2409.  
  2410. Data for attributes and parameters are contained in descriptor records. The
  2411. attributes and parameters themselves are identified by keywords. The AEKeyword
  2412. data type is defined as a four-character code.
  2413.  
  2414.    TYPE  AEKeyword = PACKED ARRAY[1..4] OF Char;
  2415.                                               {keyword for a descriptor }
  2416.                                               { record}
  2417.  
  2418. Constants are typically used for keywords. Shown here is a list of these keyword
  2419. constants, their four-character codes, and the attributes and parameters they
  2420. represent.
  2421.  
  2422.    Attribute keyword                Value      Description
  2423.  
  2424.    keyAddressAttr                     'addr'      Address of target application
  2425.    keyEventClassAttr                'evcl'      Event class of Apple event
  2426.    keyEventIDAttr                     'evid'      Event ID of Apple event
  2427.    keyEventSourceAttr             'esrc'       Source of the Apple event
  2428.    keyInteractLevelAttr             'inte'      Settings for allowing the Apple
  2429.    Event
  2430.                                                                       Manager to
  2431.                                                                       bring a
  2432.                                                                       server
  2433.  
  2434.                                                                       to the
  2435.                                                                       foreground
  2436.    keyMissedKeywordAttr       'miss'     First required parameter remaining in
  2437.    an
  2438.                                                                       Apple
  2439.                                                                       event
  2440.    keyOptionalKeywordAttr    'optk'     List of optional parameters for the
  2441.    Apple 
  2442.                                                                       event
  2443.    keyReturnIDAttr                   'rtid'       Return ID for reply Apple
  2444.    event 
  2445.    keyTimeoutAttr                     'timo'    Length of time in ticks that the
  2446.    client will 
  2447.                                                                       wait for a
  2448.                                                                       reply or a
  2449.                                                                       result
  2450.                                                                       from the
  2451.                                                                       server
  2452.    keyTransactionIDAttr           'tran'     Transaction ID identifying a series
  2453.    of Apple 
  2454.                                                                       events
  2455.  
  2456.    Parameter keyword               Value     Description
  2457.  
  2458.    keyDirectObject                      '––––'     Direct parameter
  2459.    keyErrorNumber                   'errn'      Error number parameter
  2460.    keyErrorString                        'errs'       Error string parameter
  2461.    keyProcessSerialNumber     'psn '      Process serial number parameter
  2462.  
  2463. A data structure of type AEKeyDesc consists of a keyword and a descriptor
  2464. record. This data structure, called a keyword-specified descriptor record, is
  2465. used by the Apple Event Manager to fully identify and describe an attribute or a
  2466. parameter of an Apple event.
  2467.  
  2468.    TYPE  AEKeyDesc =        {keyword-specified descriptor record}
  2469.          RECORD
  2470.             descKey:         AEKeyword;      {keyword}
  2471.             descContent:     AEDesc          {descriptor record};
  2472.    END;
  2473.  
  2474. Figure 6-4 illustrates a keyword-specified descriptor record for the event class
  2475. attribute of an Open Documents event. The keyEventClassAttr keyword identifies
  2476. its descriptor record as containing event class data. The data is of the
  2477. typeType descriptor type, and the data identifies the event class as
  2478. kCoreEventClass.
  2479.  
  2480. ¿ Figure 6-4   A keyword-specified descriptor record for the event class
  2481. attribute of an Open Documents event ø 
  2482.  
  2483. When extracting data from an Apple event, you use Apple Event Manager functions
  2484. to return data in a buffer specified by a pointer, or to return descriptor
  2485. records containing the data, or to return lists of descriptor records (called
  2486. descriptor lists) containing the data. As previously noted, the descriptor
  2487. record (of data type AEDesc) is the fundamental structure in Apple events, and
  2488. it contains a handle to data. A descriptor list is a data structure of type
  2489. AEDescList defined by the data type AEDesc—that is, a descriptor list is a
  2490. descriptor record that contains a list of other descriptor records.
  2491.  
  2492.    TYPE  AEDescList = AEDesc;  {list of descriptor records}
  2493.  
  2494. An example of a descriptor list that you will be using is the direct parameter
  2495. for the Open Documents event. As illustrated in Figure 6-5, this descriptor list
  2496. is a list of descriptor records that contain alias records to filenames. (The
  2497. Alias Manager chapter of this volume describes alias records in detail.)
  2498.  
  2499. ¿ Figure 6-5   A descriptor list for a list of aliases ø 
  2500.  
  2501. Closely related to a descriptor list is a structure of data type AERecord; in
  2502. fact, it is defined by the data type AEDescList.
  2503.  
  2504.    TYPE  AERecord = AEDescList;    {list of keyword-specified }
  2505.                                    { descriptor records}
  2506.  
  2507. While a descriptor list is a descriptor record that contains a list of other
  2508. descriptor records, an AE record of data type AERecord contains a list of
  2509. keyword-specified descriptor records describing parameters. A descriptor list of
  2510. data type AERecord contains no attributes, only parameters.
  2511.  
  2512. There is one final data structure to consider: the Apple event record. An Apple
  2513. event record is a structure of data type AppleEvent defined as an AE record. It
  2514. is used for describing a full-fledged Apple event.
  2515.  
  2516.    TYPE  AppleEvent = AERecord;  {list of attributes and parameters }
  2517.                                  { necessary for an Apple event}
  2518.  
  2519. An Apple event record is basically a descriptor record (of descriptor type
  2520. typeAppleEvent) with a handle to a list of keyword-specified descriptor records.
  2521. These descriptor records describe the attributes and parameters for an Apple
  2522. event. When you use the AECreateAppleEvent function, the Apple Event Manager
  2523. creates an Apple event record containing the attributes for an Apple event’s
  2524. event class, event ID, target address, return ID, and transaction ID. You then
  2525. use Apple Event Manager functions such as AEPutParamDesc to add parameters to
  2526. the Apple event. Figure 6-6 shows an example of an Apple event—a structure
  2527. containing a list of keyword-specified descriptor records that name the
  2528. attributes and parameters of an Open Documents event.
  2529.  
  2530. ¿ Figure 6-6   Data structures within an Open Documents event ø 
  2531.  
  2532. The internal structure of an Apple event record is nearly identical to an AE
  2533. record. They differ in the content referred to by the data handles that they
  2534. contain: the former has a list of attributes and, possibly, parameters referred
  2535. by its handle; the latter contains only parameters. However, you can pass an
  2536. Apple event record to any Apple Event Manger function that expects an AE record.
  2537. Since both are structures of data type AEDescList, which is derived from the
  2538. data type AEDesc, you can pass Apple event records, AE records, descriptor
  2539. lists, and descriptor records to any Apple Event Manager functions that expect
  2540. records of data type AEDesc.
  2541.  
  2542. The data in Apple event records, AE records, and descriptor lists—all of which
  2543. are descriptor records—is private to the Apple Event Manager. The Apple Event
  2544. Manager maintains these different data structures because it stores different
  2545. kinds of information in their handles. Although all the information you need is
  2546. available by calling the appropriate Apple Event Manager functions, the Apple
  2547. Event Manager needs a way to tell these different descriptor records apart. It
  2548. does this by looking at their data types.
  2549. _______________________________________________________________________________
  2550.  
  2551. æKY Responding…to…Apple…Events
  2552. æC »Responding to Apple Events                                     The Apple Event Manager
  2553. _______________________________________________________________________________
  2554.  
  2555. A client application uses the Apple Event Manager to create and send an Apple
  2556. event requesting a service. A server application responds by using the Apple
  2557. Event Manager to process the Apple event, to extract data from the attributes
  2558. and parameters of the Apple event, and to return a result to the client
  2559. application. The server provides its own routines for performing the action
  2560. requested by the client’s Apple event.
  2561.  
  2562. As its first step in supporting Apple events, your application must be able to
  2563. respond to the required Apple events sent by the Finder. If you plan to
  2564. implement publish and subscribe capabilities, your application must respond to
  2565. the Apple events sent by the Edition Manager. You can also respond to Apple
  2566. events sent by your own application or by other applications. This section
  2567. provides a quick overview of the steps your application takes in responding to
  2568. Apple events.
  2569.  
  2570. To respond to Apple events, your application must
  2571.  
  2572.   • test for high-level events in its event loop
  2573.  
  2574.   • use the AEProcessAppleEvent function to process Apple events
  2575.  
  2576.   • provide handler routines for the Apple events it supports
  2577.  
  2578.   • use Apple Event Manager functions to extract the parameters and attributes 
  2579.      from Apple events
  2580.  
  2581.   • use the AEInteractWithUser function—if your application requires input from 
  2582.      the user when your application is responding to an Apple event—to bring
  2583.      your 
  2584.      application to the foreground to interact with the user
  2585.  
  2586.   • return a result for the client
  2587.  
  2588. Note that in order for your application to respond to Apple events sent from
  2589. remote computers, the user of your application must allow network users to link
  2590. to your application. The user does this by selecting your application from the
  2591. Finder and choosing Sharing from the File menu and then clicking the Allow
  2592. Remote Program Linking checkbox. If the user has not yet started program
  2593. linking, the Sharing command offers to display the Sharing Setup control panel
  2594. so that the user can start program linking. The user must also authorize remote
  2595. users for program linking by using the Users and Groups control panel. Program
  2596. linking and setting up authenticated sessions are described in the
  2597. Program-to-Program Communications chapter in this volume.
  2598.  
  2599. An Apple event (like all high-level events) is identified by a message class of
  2600. kHighLevelEvent in the what field of the event record. You test the what field
  2601. of the event record to determine whether an event is a high-level event. If the
  2602. what field contains the kHighLevelEvent constant and your application defines
  2603. any high-level events other than Apple events, test the message field of the
  2604. event record to determine whether the high-level event is something other than
  2605. an Apple event. If the high-level event is not one that you’ve defined for your
  2606. application, assume that it is an Apple event. (Note that you are encouraged to
  2607. use Apple events instead of defining your own high-level events whenever
  2608. possible.)
  2609.  
  2610. After determining that an event is an Apple event, use the AEProcessAppleEvent
  2611. function to let the Apple Event Manager identify the event. Figure 6-7 shows how
  2612. the SurfWriter application accepts and begins to process an Apple event sent by
  2613. the Finder.
  2614.  
  2615. ¿ Figure 6-7   Accepting and processing an Open Documents event ø 
  2616.  
  2617. The AEProcessAppleEvent function begins processing the Apple event. The
  2618. AEProcessAppleEvent function identifies the Apple event by examining the data in
  2619. the event class and event ID attributes. The AEProcessAppleEvent function in
  2620. turn uses that data to call the Apple event handler that your application
  2621. provides for that event. An Apple event handler is a function that extracts the
  2622. pertinent data from the Apple event, performs the action requested by the Apple
  2623. event, and returns a result. For example, if the event has an event class of
  2624. kCoreEventClass and an event ID of kAEOpenDocuments, the AEProcessAppleEvent
  2625. function calls your application’s routine for handling the Open Documents event.
  2626.  
  2627. You install Apple event handlers by using the AEInstallEventHandler function.
  2628. This function creates an Apple event dispatch table that the Apple Event Manager
  2629. uses to map Apple events to handlers in your application. After being called by
  2630. the AEProcessAppleEvent function to process an Apple event, the Apple Event
  2631. Manager reads the Apple event dispatch table and, if your application has
  2632. installed a handler for that Apple event, calls your handler to finish
  2633. responding to the event. Figure 6-8 shows how the flow of control passes from
  2634. your application to the Apple Event Manager and back to your application.
  2635.  
  2636. ¿ Figure 6-8   The Apple Event Manager calling the handler for an Open Documents
  2637. event ø 
  2638.  
  2639. Your Apple event handlers must generally perform the following tasks:
  2640.  
  2641.   • extract the parameters and attributes for the Apple event
  2642.  
  2643.   • check that all the required parameters have been extracted
  2644.  
  2645.   • set user interaction level preferences if necessary and, if your application
  2646.   needs 
  2647.      to interact with the user, use the AEInteractWithUser function to bring it
  2648.      to the
  2649.      foreground
  2650.  
  2651.   • perform the action requested by the Apple event
  2652.  
  2653.   • dispose of any copies of descriptor records that have been created
  2654.  
  2655.   • return a result for the client
  2656.  
  2657. You must use Apple Event Manager functions to extract the data from Apple
  2658. events. You can also use Apple Event Manager functions to get data out of
  2659. descriptor records, descriptor lists, and AE records. Most of these routines are
  2660. available in two forms: one that uses a buffer to return a copy of the desired
  2661. data and one that returns a copy of the descriptor record containing the data.
  2662. The following list shows the main functions you can use to access the data of an
  2663. Apple event.
  2664.  
  2665. Function                                Description
  2666.  
  2667. AEGetParamPtr                    Uses a buffer to return the data contained in a
  2668.                                                  parameter; used, for example,
  2669.                                                  to extract the result code
  2670.                                                  from the keyErrorNumber
  2671.                                                  parameter of a reply Apple
  2672.                                                  event.
  2673.  
  2674. AEGetParamDesc                 Returns the descriptor record or descriptor list
  2675. for a
  2676.                                                  parameter; used, for example,
  2677.                                                  to extract the descriptor
  2678.                                                  list for a list of alias
  2679.                                                  records specified in the direct
  2680.                                                  parameter of the Open Documents
  2681.                                                  event.
  2682.  
  2683. AEGetAttributePtr               Uses a buffer to return the data contained in an
  2684. attribute;
  2685.                                                  used, for example, to determine
  2686.                                                  the source of an Apple
  2687.                                                  event by extracting the data
  2688.                                                  from the
  2689.                                                  keyEventSourceAttr attribute.
  2690.  
  2691. AEGetAttributeDesc            Returns the descriptor record for a parameter;
  2692. used, for
  2693.                                                   example, to make a copy of a
  2694.                                                   descriptor record
  2695.                                                   containing the address of an
  2696.                                                   application.
  2697.  
  2698. AECountItems                     Returns the number of descriptor records in a
  2699. descriptor
  2700.                                                  list; used, for example, to
  2701.                                                  determine the number of alias
  2702.                                                  records for documents specified
  2703.                                                  in the direct parameter
  2704.                                                  of the Open Documents event.
  2705.  
  2706. AEGetNthPtr                       Uses a buffer to return the data for a
  2707. descriptor record
  2708.                                                 that is contained in a
  2709.                                                 descriptor list; used, for
  2710.                                                 example, to
  2711.                                                 extract a document’s alias
  2712.                                                 record from the descriptor list
  2713.                                                 specified in the direct
  2714.                                                 parameter of the Open Documents
  2715.                                                 event.
  2716.  
  2717. AEGetNthDesc                   Returns a descriptor record from a descriptor
  2718. list; used,
  2719.                                                for example, to get the
  2720.                                                descriptor record containing an
  2721.                                                alias record from the list
  2722.                                                specified in the direct parameter
  2723.                                                of the Open Documents event.
  2724.  
  2725. You can specify the descriptor type of the resulting data for these functions;
  2726. if this is different from the descriptor type of the attribute or parameter, the
  2727. Apple Event Manager attempts to coerce it to the specified type. In the direct
  2728. parameter of the Open Documents event, for example, each descriptor record in
  2729. the descriptor list is an alias record; each alias record specifies a document
  2730. to be opened. As explained in the File Manager chapter of this volume, all your
  2731. application usually needs is the file system specification (FSSpec) record of
  2732. the document. When you extract the descriptor from the descriptor list, you can
  2733. request that the Apple Event Manager return the data to your application as a
  2734. file system specification record instead of as an alias record.
  2735.  
  2736. After extracting all known parameters, your handler should check that it
  2737. retrieved all the required parameters by checking whether the
  2738. keyMissedKeywordAttr attribute exists. If the attribute exists, then your
  2739. handler has not retrieved all the required parameters, and it should return an
  2740. error.
  2741.  
  2742. In some cases, the server may need to interact with the user when it handles an
  2743. Apple event. For example, your handler for the Print Documents event may need to
  2744. display a print options dialog box and get settings from the user before
  2745. printing. Your handler should always use the AEInteractWithUser function before
  2746. displaying a dialog box or alert box or otherwise interacting with the user. By
  2747. specifying one of these flags to the AESetInteractionAllowed function, you can
  2748. set your application’s user interaction level preferences.
  2749.  
  2750. Flag                                           Description
  2751.  
  2752. kAEInteractWithSelf            User interaction with your server application in
  2753.                                                    response to an Apple event
  2754.                                                    may be allowed only when
  2755.                                                    the client application is
  2756.                                                    your own application—that is,
  2757.                                                    only when your application is
  2758.                                                    sending the Apple event
  2759.                                                    to itself.
  2760.  
  2761. kAEInteractWithLocal         User interaction with your server application in
  2762.                                                    response to an Apple event
  2763.                                                    may be allowed only if the
  2764.                                                    client application is on the
  2765.                                                    same computer as your
  2766.                                                    application; this is the
  2767.                                                    default if the
  2768.                                                    AESetInteractionAllowed
  2769.                                                    function is not used.
  2770.  
  2771. kAEInteractWithAll             User interaction with your server application in
  2772.                                                     response to an Apple event
  2773.                                                     may be allowed for any
  2774.                                                     client application on any
  2775.                                                     computer.
  2776.  
  2777. For a server application to allow user interaction in response to the client’s
  2778. Apple event, two conditions must be met. First, the client application must
  2779. request that your server application allow user interaction. Second, your server
  2780. application must allow user interaction in response to the Apple event sent from
  2781. that client application as described in the previous list. If these conditions
  2782. are met and your application needs to interact with the user, the
  2783. AEInteractWithUser function brings your application to the foreground if it
  2784. isn’t already in the foreground. Your application can then display its dialog
  2785. box or alert box or otherwise interact with the user. AEInteractWithUser brings
  2786. your server application to the front either directly or after the user responds
  2787. to a notification request.
  2788.  
  2789. When your application acts on an Apple event, it should perform the standard
  2790. action requested by that event. For example, if the Apple event is the Open
  2791. Documents event, your application should open the specified documents in titled
  2792. windows just as if the user had selected each document from the Finder and then
  2793. chosen Open from the File menu. You should strive to create routines that can be
  2794. called in response to both user events and Apple events. To do this, you need to
  2795. isolate code for interacting with the user from the code that performs the
  2796. requested action—such as opening a document. You then call the code that
  2797. performs the requested action from your Apple event handler.
  2798.  
  2799. When you extract a descriptor record by using the AEGetParamDesc,
  2800. AEGetAttributeDesc, AEGetNthDesc, or AEGetKeyDesc functions, the Apple Event
  2801. Manager creates a copy of the descriptor record for you to use. When your
  2802. handler is finished using a copy of a descriptor record, you should dispose of
  2803. it—and thereby deallocate the memory it uses—by calling the AEDisposeDesc
  2804. function.
  2805.  
  2806. The required Apple events ask your application to perform tasks—open your
  2807. application, open or print documents, or quit your application. Other Apple
  2808. events may ask your application to return data. For example, if your application
  2809. is a spelling checker, the client probably expects data in the form of a list of
  2810. misspelled words to be returned from your application. If a reply is requested,
  2811. the Apple Event Manager prepares a reply Apple event for the client by passing a
  2812. default reply Apple event to your handler. The default reply Apple event has no
  2813. parameters when it is passed to your handler. Your handler can add any
  2814. parameters to the reply Apple event. If your application is a spelling checker,
  2815. for example, you can return a list of misspelled words in a parameter.
  2816.  
  2817. Your handler routine should always set its function result either to noErr if it
  2818. successfully handles the Apple event or to a nonzero result code if an error
  2819. occurs. If an error occurs, the Apple Event Manager adds a keyErrorNumber
  2820. parameter to the reply Apple event; this parameter contains the result code that
  2821. your handler returns. The client should check whether the keyErrorNumber
  2822. parameter exists to determine whether your handler performed the requested
  2823. action. In addition to returning a result code, your handler can also return an
  2824. error string in the keyErrorString parameter of the reply Apple event. The
  2825. client can use this string in an error message to the user.
  2826.  
  2827. If the source requested a reply, the Apple Event Manager returns the reply Apple
  2828. event to the source. The reply Apple event is identified by the event class
  2829. kCoreEventClass and by the event ID kAEAnswer. When you have finished using the
  2830. reply Apple event, you should dispose of it—and thereby deallocate the memory it
  2831. uses—by calling the AEDisposeDesc function.
  2832.  
  2833. When your handler returns a result code to the Apple Event Manager, you have
  2834. finished your response to the client’s Apple event. Figure 6-9 shows the entire
  2835. process of responding to an Apple event. The next section describes how to send
  2836. an Apple event.
  2837.  
  2838. ¿ Figure 6-9   Responding to an Open Documents eventi.Open Documents event ø 
  2839.  
  2840. _______________________________________________________________________________
  2841.  
  2842. æKY Requesting…Services…Through…Apple…Events
  2843. æC »Requesting Services Through Apple Events                       The Apple Event Manager
  2844. _______________________________________________________________________________
  2845.  
  2846. Your application can use Apple events to request services from other
  2847. applications. By using Finder events, for example, your application can simulate
  2848. the behavior of the Finder by requesting that the Finder perform such operations
  2849. as launching an application on your behalf. By using functional-area Apple
  2850. events, your application can request services from applications related to your
  2851. own—for example, asking a spelling checker application to check the text in a
  2852. document created by your application. All publicly available Apple events are
  2853. defined and published in the Apple Event Registry.  Consult the Apple Event
  2854. Registry  for the format and function of Apple events that your application may
  2855. wish to send.
  2856.  
  2857. The previous section describes how a server application responds to a client
  2858. application’s request for services. This section briefly describes the steps
  2859. your application must take to act as a client application and request such
  2860. services. To request a service through an Apple event, your application must
  2861.  
  2862.   • create an Apple event by calling the AECreateAppleEvent function
  2863.  
  2864.   • use Apple Event Manager functions to add parameters and any other necessary 
  2865.      attributes to the Apple event
  2866.  
  2867.   • call the AESend function to send the Apple event
  2868.  
  2869.   • dispose of any copies of descriptor records that you have created
  2870.  
  2871.   • process the reply Apple event (optional)
  2872.  
  2873. Use the AECreateAppleEvent function to create an Apple event record. Using the
  2874. arguments you pass to the AECreateAppleEvent function, the Apple Event Manager
  2875. constructs the data structures describing the event class, the event ID, and the
  2876. target address attributes of an Apple event. The event class and event ID, of
  2877. course, identify the particular event you wish to send. The target address
  2878. identifies the application to which you wish to send the Apple event.
  2879.  
  2880. To act as a server application for your application, the target must support
  2881. high-level events and must be open. The server can be your own application,
  2882. another application running on the user’s computer, or an application running on
  2883. another user’s computer connected to the network. Your application should offer
  2884. some facility to launch a server application if it is not already running. It is
  2885. recommended that you use the Open Selection event (identified by the event class
  2886. kAEFinderEvents and the event ID kAEOpenSelection) to request that the Finder
  2887. launch applications; however, the Process Manager also provides a means for your
  2888. application to launch other applications. See the Apple Event Registry  for
  2889. information on Finder events, and see the Process Management chapter in this
  2890. volume for information on using the Process Manager.
  2891.  
  2892. Your application should also offer a facility to allow the user to choose among
  2893. the various applications available as servers. The PPCBrowser function allows
  2894. users to select target applications on the user’s computer as well as those
  2895. available on computers connected to the network.  The PPCBrowser function
  2896. presents a standard user interface for choosing a target application, much as
  2897. the Standard File Package provides a standard user interface for opening and
  2898. saving files. See the Program-to-Program Communications Toolbox chapter of this
  2899. volume for details on using the PPCBrowser function.
  2900.  
  2901. If the server application is on a remote computer on a network, the user of that
  2902. computer must allow program linking to the server application. The user of the
  2903. server application does this by selecting the application from the Finder and
  2904. choosing Sharing from the File menu and then clicking the Allow Remote Program
  2905. Linking checkbox. If the user has not yet started program linking, the Sharing
  2906. command offers to display the Sharing Setup control panel so that the user can
  2907. start program linking. The user must also authorize remote users for program
  2908. linking by using the Users and Groups control panel. Program linking and setting
  2909. up authenticated sessions are described in the Program-to-Program Communications
  2910. chapter in this volume.
  2911.  
  2912. There are two other attributes you specify in the AECreateAppleEvent function:
  2913. the reply ID and the transaction ID. For the reply ID attribute, you’ll usually
  2914. specify the kAutoGenerateReturnID constant to the AECreateAppleEvent function.
  2915. This ensures that the Apple Event Manager generates a unique return ID for the
  2916. reply Apple event returned from the server. For the transaction ID attribute,
  2917. you’ll usually specify the kAnyTransactionID constant, which indicates that this
  2918. Apple event is not one of a series of interdependent Apple events.
  2919.  
  2920. The Apple event record created with the AECreateAppleEvent function serves as a
  2921. template for the Apple event you want to send. To add the remaining attributes
  2922. and parameters necessary for your Apple event, you must use these additional
  2923. Apple Event Manager functions.
  2924.  
  2925. Function                             Description
  2926.  
  2927. AEPutParamPtr                 Takes a keyword, descriptor type, and a pointer to
  2928. data,
  2929.                                                converts them into a parameter,
  2930.                                                and adds the parameter
  2931.                                                to or replaces it in an Apple
  2932.                                                event record; used, for
  2933.                                                example, to place numbers into
  2934.                                                the parameters of an
  2935.                                                Apple event requesting that the
  2936.                                                server perform a
  2937.                                                calculation.
  2938.  
  2939. AEPutParamDesc               Takes a keyword and a descriptor record, converts
  2940. them
  2941.                                                 into a parameter, and adds the
  2942.                                                 parameter to or replaces it
  2943.                                                 in an Apple event record; used,
  2944.                                                 for example, to place a
  2945.                                                 descriptor list containing alias
  2946.                                                 records into the direct
  2947.                                                 parameter of an Apple event that
  2948.                                                 requests a server to
  2949.                                                 manipulate files.
  2950.  
  2951. AEPutAttributePtr             Takes a keyword, descriptor type, and a pointer to
  2952. data,
  2953.                                                 converts them into an attribute,
  2954.                                                 and adds the attribute to
  2955.                                                 or replaces it in an Apple event
  2956.                                                 record; used, for
  2957.                                                 example, to change the event ID
  2958.                                                 of an Apple event
  2959.                                                 record that is waiting to be
  2960.                                                 sent.
  2961.  
  2962. AEPutAttributeDesc          Takes a keyword and a descriptor record, converts
  2963. them
  2964.                                                 into an attribute, and adds the
  2965.                                                 attribute to or replaces it in
  2966.                                                 an Apple event record; used, for
  2967.                                                 example, to replace the
  2968.                                                 descriptor record used for the
  2969.                                                 target address attribute in
  2970.                                                 an Apple event record waiting to
  2971.                                                 be sent.
  2972.  
  2973. Descriptor records and descriptor lists are the basic components from which an
  2974. Apple event record is constructed; these are passed to the AEPutParamDesc and
  2975. AEPutAttributeDesc functions. Use the following functions to create descriptor
  2976. records and descriptor lists.
  2977.  
  2978. Function                             Description
  2979.  
  2980. AECreateDesc                     Takes a descriptor type and a pointer to data
  2981. and converts
  2982.                                                them into a descriptor record;
  2983.                                                used, for example, to create
  2984.                                                a descriptor record that is used
  2985.                                                as an attribute or a
  2986.                                                parameter in an Apple event
  2987.                                                record.
  2988.  
  2989. AEPutPtr                              Takes a descriptor type and a pointer to
  2990. data, converts
  2991.                                                 them into a descriptor record,
  2992.                                                 and adds the record to a
  2993.                                                 descriptor list; used, for
  2994.                                                 example, to place into a
  2995.                                                 descriptor list a number that is
  2996.                                                 used as the parameter of
  2997.                                                 an Apple event requesting a
  2998.                                                 calculation.
  2999.  
  3000. AEPutDesc                            Adds a descriptor record to a descriptor
  3001. list; used, for
  3002.                                                  example, to add into the
  3003.                                                  descriptor list an alias record
  3004.                                                  that is used as the direct
  3005.                                                  parameter of an Apple event
  3006.                                                  requesting file manipulation.
  3007.  
  3008. After you add all the attributes and parameters required for the Apple event,
  3009. use the AESend function to send the Apple event. The Apple Event Manager uses
  3010. the Event Manager to transmit the Apple event to the server application.
  3011.  
  3012. The AESend function requires that you specify whether and how your application
  3013. should wait for a reply from the server. When the server receives your Apple
  3014. event, the Apple Event Manager prepares a reply Apple event for your application
  3015. by passing a default reply Apple event to the server. The Apple Event Manager
  3016. returns any nonzero result code from the server’s handler in the keyErrorNumber
  3017. parameter of the reply Apple event. If your application wants to return an error
  3018. string, add it to the reply Apple event in the keyErrorString parameter. The
  3019. server can also use this reply Apple event to return any data you requested—for
  3020. example, the results of a numerical calculation or a list of misspelled words.
  3021.  
  3022. You specify how your application should wait for a reply by using one of these
  3023. flags in the sendMode parameter of the AESend function.
  3024.  
  3025. Flag                                 Description
  3026.  
  3027. kAENoReply                 Your application does not want a reply Apple event;
  3028. the
  3029.                                            server processes your Apple event as
  3030.                                            soon as it has the 
  3031.                                            opportunity.
  3032.  
  3033. kAEQueueReply           Your application wants a reply Apple event; the reply
  3034.                                            appears in your event queue as soon
  3035.                                            as the server has the
  3036.                                            opportunity to process and respond to
  3037.                                            your Apple event.
  3038.  
  3039. kAEWaitReply              Your application wants a reply Apple event and is
  3040. willing to
  3041.                                           give up the processor while waiting
  3042.                                           for the reply; for
  3043.                                           example, if the server application is
  3044.                                           on the same computer
  3045.                                           as your application, your application
  3046.                                           yields the processor to
  3047.                                           allow the server to respond to your
  3048.                                           Apple event.
  3049.  
  3050. If you specify the kAEWaitReply flag, you may provide an idle function. This
  3051. function should process any events that occur while your application is waiting
  3052. for a reply. You supply a pointer to your idle function as a parameter to the
  3053. AESend function. So that your application can process other Apple events while
  3054. it is waiting for a reply, you can also specify an optional filter function to
  3055. the AESend function that filters Apple events.
  3056.  
  3057. If your Apple event may require the user to interact with the server application
  3058. (for example, to specify print or file options), you can communicate your
  3059. user-interaction preferences to the server by specifying one of the following
  3060. flags in the sendMode parameter of the AESend function.
  3061.  
  3062. Flag                                 Description
  3063.  
  3064. kAENeverInteract       The server application should never interact with the
  3065. user
  3066.                                           in response to this Apple event. If
  3067.                                           this flag is set,
  3068.                                           AEInteractWithUser does not bring the
  3069.                                           server application to
  3070.                                           the foreground (this is the default
  3071.                                           when an Apple event is
  3072.                                           sent to a remote application).
  3073.  
  3074. kAECanInteract            The server application can interact with the user in
  3075. response
  3076.                                           to this Apple event—by convention, if
  3077.                                           the user needs to 
  3078.                                           supply information to the server. If
  3079.                                           this flag is set and the
  3080.                                           server allows interaction,
  3081.                                           AEInteractWithUser brings the 
  3082.                                           server application to the foreground
  3083.                                           (this is the default 
  3084.                                           when an Apple event is sent to a local
  3085.                                           application).
  3086.  
  3087. kAEAlwaysInteract       The server application can interact with the user in 
  3088.                                            response to this Apple event—by
  3089.                                            convention, even if no 
  3090.                                            information is needed from the user.
  3091.                                            If this flag is set and 
  3092.                                            the server allows interaction,
  3093.                                            AEInteractWithUser brings 
  3094.                                            the server application to the
  3095.                                            foreground. The Apple Event
  3096.                                            Manager does not distinguish between
  3097.                                            this flag and the
  3098.                                            kAECanInteract flag—distinguishing
  3099.                                            between them is the
  3100.                                            responsibility of the server
  3101.                                            application.
  3102.  
  3103. kAECanSwitchLayer     If both the client and server allow interaction and this
  3104. flag
  3105.                                             is set, AEInteractWithUser brings
  3106.                                             the server directly to the 
  3107.                                             foreground if adherence to the
  3108.                                             principle of user control 
  3109.                                             allows. If the action would be
  3110.                                             contrary to this principle, 
  3111.                                             AEInteractWithUser uses the
  3112.                                             Notification Manager to 
  3113.                                             request that user bring the server
  3114.                                             application to the 
  3115.                                             foreground. If both the client and
  3116.                                             server allow interaction 
  3117.                                             and this flag is not set,
  3118.                                             AEInteractWithUser always uses the
  3119.                                             Notification Manager to request that
  3120.                                             the user bring the 
  3121.                                             server application to the
  3122.                                             foreground.
  3123.  
  3124. The server can set its own interaction preferences. The interaction of your
  3125. client’s preferences and the server’s is explained in “Interacting With the
  3126. User” later in this chapter.
  3127.  
  3128. After you send an Apple event, your application is responsible for disposing of
  3129. the Apple event record—and thereby deallocating the memory it uses—by calling
  3130. the AEDisposeDesc function. If you create one descriptor record and add it to
  3131. another, the Apple Event Manager creates a copy of the newly created one and
  3132. adds that copy to the existing one. For example, you might use the AECreateDesc
  3133. function to create a descriptor record that you wish to add to an Apple event.
  3134. When you use the AEPutParamDesc function, it creates a copy of your newly
  3135. created descriptor record and adds that copy as a parameter to an existing Apple
  3136. event.
  3137.  
  3138. Your application should dispose of all the descriptor records that are created
  3139. in order to add parameters and attributes to an Apple event. You normally
  3140. dispose of your Apple event and its reply after you receive a result from the
  3141. AESend function. You should dispose of these even if AESend returns an error
  3142. result. If your application requests a reply Apple event, your application must
  3143. also dispose of the reply Apple event when finished processing it.
  3144.  
  3145. Your application can request a reply Apple event. If you specify the
  3146. kAEWaitReply flag, the reply Apple event is returned in a parameter you pass to
  3147. the AESend function. If you specify the kAEQueueReply flag to the AESend
  3148. function, the reply Apple event is returned in the event queue. In this case,
  3149. the reply is identified by the event class kCoreEventClass and the event ID
  3150. kAEAnswer; your application processes reply events that it receives in its event
  3151. queue in the same manner that server applications process Apple events, as
  3152. described earlier in “Responding to Apple Events.” 
  3153.  
  3154. Your application should check for the keyErrorNumber parameter of the reply
  3155. Apple event to ensure that the server performed the requested action. Any error
  3156. messages that the server returns for you to display to your user will appear in
  3157. the keyErrorString parameter.
  3158.  
  3159. When your handler is finished using a copy of a descriptor record used in the
  3160. reply Apple event, you should dispose of them both—and thereby deallocate the
  3161. memory they use—by calling the AEDisposeDesc function.
  3162.  
  3163. The next section, “Using the Apple Event Manager,” describes in greater detail
  3164. the routines necessary for sending and responding to Apple events.
  3165.  
  3166. _______________________________________________________________________________
  3167.  
  3168. æKY Using…the…Apple…Event…Manager…Volume…VI
  3169. æC »Using the Apple Event Manager Volume VI                        The Apple Event Manager
  3170. _______________________________________________________________________________
  3171.  
  3172. The following sections explain in more detail how to use the Apple Event Manager
  3173. to receive, accept, and send Apple events. The first two sections describe how
  3174. to accept and process Apple events and how to install entries into the Apple
  3175. event dispatch table. The following section fully explains how your application
  3176. should handle the required Apple events, and it provides code that shows sample
  3177. handlers for the required Apple events.
  3178.  
  3179. Additional sections describe how to
  3180.  
  3181.   • handle events that support publish and subscribe features
  3182.  
  3183.   • get data out of an Apple event
  3184.  
  3185.   • write handlers that perform the action requested by an Apple event
  3186.  
  3187.   • reply to an Apple event
  3188.  
  3189.   • dispose of Apple event data structures
  3190.  
  3191.   • interact with the user when processing an Apple event
  3192.  
  3193.   • create an Apple event
  3194.  
  3195.   • send an Apple event
  3196.  
  3197.   • write an idle function
  3198.  
  3199.   • write a reply filter function
  3200.  
  3201.   • write and install coercion handlers
  3202.  
  3203.   • use the Application Died event to ascertain the termination of an
  3204.   application 
  3205.      that has been launched by your application
  3206.  
  3207. The Apple Event Manager is available only in system software version 7.0. Use
  3208. the Gestalt function with the gestaltAppleEventsAttr selector to determine
  3209. whether the Apple Event Manager is available. In the response parameter, the bit
  3210. defined by the constant gestaltAppleEventsPresent is set if the Apple Event
  3211. Manager is available.     
  3212.  
  3213.    CONST  gestaltAppleEventsAttr    = 'evnt';  {Gestalt selector}
  3214.           gestaltAppleEventsPresent = 0;       {if this bit is set, then }
  3215.                                                {Apple Event Mgr’s available}
  3216. _______________________________________________________________________________
  3217.  
  3218. æKY Accepting…an…Apple…Event
  3219. æC »Accepting an Apple Event                                       The Apple Event Manager
  3220. _______________________________________________________________________________
  3221.  
  3222. To accept Apple events (or any other high-level events), you must set the
  3223. appropriate flags in your application’s 'SIZE' resource and include code to
  3224. handle high-level events in your application’s main event loop. 
  3225.  
  3226. Two flags in the 'SIZE' resource determine whether an application receives
  3227. high-level events: 
  3228.  
  3229.   • The isHighLevelEventAware flag must be set for your application to receive
  3230.   any
  3231.      high-level events.
  3232.  
  3233.   • The localAndRemoteHLEvents flag must be set for your application to receive 
  3234.      high-level events sent from another computer on the network.
  3235.  
  3236. Note that in order for your application to respond to Apple events sent from
  3237. remote computers, the user of your application must also allow network users to
  3238. link to your application. The user does this by selecting your application from
  3239. the Finder and choosing Sharing from the File menu and then clicking the Allow
  3240. Remote Program Linking checkbox. If the user has not yet started program
  3241. linking, the Sharing command offers to display the Sharing Setup control panel
  3242. so that the user can start program linking. The user must also authorize remote
  3243. users for program linking by using the Users and Groups control panel. Program
  3244. linking and setting up authenticated sessions are described in the
  3245. Program-to-Program Communications chapter in this volume.
  3246.  
  3247. For a complete description of the 'SIZE' resource, see the Event Manager chapter
  3248. in this volume.
  3249.  
  3250. Apple events (and other high-level events) are identified by a message class of
  3251. kHighLevelEvent in the what field of the event record. You can test the what
  3252. field of the event record to determine whether the event is a high-level event.
  3253.  
  3254. Listing 6-1 is an example of a procedure called from an application’s main event
  3255. loop that handles events, including high-level events. The procedure determines
  3256. the type of event received and then calls another routine to take the
  3257. appropriate action.
  3258.  
  3259. ¿ Listing 6-1   A DoEvent procedure
  3260.  
  3261. PROCEDURE DoEvent (event: EventRecord);
  3262.  
  3263. BEGIN              
  3264.     CASE event.what OF      {determine the type of event}
  3265.        mouseDown:
  3266.           DoMouseDown (event);
  3267.        .
  3268.        . {handle other kinds of events}
  3269.        .
  3270.        {handle high-level events, including Apple events}
  3271.        kHighLevelEvent:
  3272.           DoHighLevelEvent (event);
  3273.      END;
  3274. END; 
  3275.  
  3276. Listing 6-2 is an example of a DoHighLevelEvent procedure that handles Apple
  3277. events and also handles the high-level event identified by the event class
  3278. mySpecialHLEventClass and the event ID mySpecialHLEventID. Note that, in most
  3279. cases, you should use Apple events to communicate with other applications. 
  3280.  
  3281. ¿ Listing 6-2   A DoHighLevelEvent procedure for handling Apple events and other
  3282. high-level events
  3283.  
  3284. PROCEDURE DoHighLevelEvent (event: EventRecord);
  3285.  
  3286. VAR
  3287.    myErr : OSErr;
  3288. BEGIN
  3289.    IF event.message = LongInt(mySpecialHLEventClass) AND
  3290.       event.where = LongInt(mySpecialHLEventID) THEN
  3291.    BEGIN
  3292.    {it's a high-level event that doesn't use AEIMP}
  3293.       myErr := HandleMySpecialHLEvent(event);
  3294.       IF myErr <> noErr THEN
  3295.          DoError(myErr);  {perform the necessary error handling}
  3296.    END;
  3297.    ELSE    {otherwise, assume that the event is an Apple event}
  3298.    BEGIN
  3299.       myErr := AEProcessAppleEvent(event);
  3300.       IF myErr <> noErr THEN
  3301.          DoError(myErr);
  3302.    END;
  3303. END;
  3304.  
  3305. If your application accepts high-level events that do not follow the Apple Event
  3306. Interprocess Messaging Protocol (AEIMP), you must dispatch these high-level
  3307. events before calling AEProcessAppleEvent. To dispatch a high-level event that
  3308. does not follow AEIMP, for each event you should check the event class, the
  3309. event ID, or both to see if the event is one that your application can handle. 
  3310.  
  3311. After receiving a high-level event (and, if appropriate, checking whether it is
  3312. a type of high-level event other than an Apple event), your application
  3313. typically calls the AEProcessAppleEvent function. The AEProcessAppleEvent
  3314. function determines the type of Apple event received, gets the event buffer that
  3315. contains the parameters and attributes of the Apple event, and calls the
  3316. corresponding Apple event handler routine in your application.
  3317.  
  3318. You should provide a handler routine for each Apple event that your application
  3319. supports. Your handler routine for a particular Apple event is responsible for
  3320. performing the action requested by the Apple event, and your handler can
  3321. optionally return data in the reply Apple event. 
  3322.  
  3323. After your handler finishes processing the Apple event and adds any parameters
  3324. to the default reply, it should return a result code to AEProcessAppleEvent. If
  3325. the client application is waiting for a reply, the Apple Event Manager returns
  3326. the reply Apple event to the client.
  3327.  
  3328. _______________________________________________________________________________
  3329.  
  3330. æKY Installing…Entries…Into…the…Apple…Event…Dispatch…Tables
  3331. æC »Installing Entries Into the Apple Event Dispatch Tables        The Apple Event Manager
  3332. _______________________________________________________________________________
  3333.  
  3334. When your application receives an Apple event, use the AEProcessAppleEvent
  3335. function to retrieve the data buffer of the event and to route the Apple event
  3336. to the appropriate Apple event handler in your application. Your application
  3337. supplies an Apple event dispatch table to provide a mapping between the Apple
  3338. events your application supports and the Apple event handlers provided by your
  3339. application.
  3340.  
  3341. To install entries into your application’s Apple event dispatch table, use the
  3342. AEInstallEventHandler function. You usually install entries for all of the Apple
  3343. events that your application accepts into your application’s Apple event
  3344. dispatch table. 
  3345.  
  3346. For each Apple event your application supports, you should install entries in
  3347. your Apple event dispatch table that specify
  3348.  
  3349.   • the event class of the Apple event
  3350.  
  3351.   • the event ID of the Apple event
  3352.  
  3353.   • the address of the Apple event handler for the Apple event
  3354.  
  3355.   • a reference constant
  3356.  
  3357. You provide this information to the AEInstallEventHandler function. In addition,
  3358. you indicate to the AEInstallEventHandler function whether the entry should be
  3359. added to your application’s Apple event dispatch table or the system Apple event
  3360. dispatch table.
  3361.  
  3362. The system Apple event dispatch table is a table in the system heap that
  3363. contains handlers that are available to all applications and processes running
  3364. on the same computer. The handlers in your application’s Apple event dispatch
  3365. table are available only to your application. If AEProcessAppleEvent cannot find
  3366. a handler for the Apple event in your application’s Apple event dispatch table,
  3367. it looks in the system Apple event dispatch table for a handler. If it doesn’t
  3368. find a handler there either, it returns the errAEEventNotHandled result code.
  3369.  
  3370.  Listing 6-3 illustrates how to add entries for the required Apple events to
  3371.  your application’s Apple event dispatch table.
  3372.  
  3373. ¿ Listing 6-3   Inserting entries for required Apple events into an
  3374. application’s Apple event dispatch table
  3375.  
  3376. myErr := AEInstallEventHandler (kCoreEventClass, kAEOpenApplication, 
  3377.                                 @MyOAPP, 0, FALSE);
  3378. IF myErr <> noErr THEN DoError(myErr);
  3379. myErr := AEInstallEventHandler (kCoreEventClass, kAEOpenDocuments, 
  3380.                                 @MyODOC, 0, FALSE);
  3381. IF myErr <> noErr THEN DoError(myErr);
  3382. myErr := AEInstallEventHandler (kCoreEventClass, kAEPrintDocuments, 
  3383.                                 @MyPDOC, 0, FALSE);
  3384. IF myErr <> noErr THEN DoError(myErr);
  3385. myErr := AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, 
  3386.                                 @MyQUIT, 0, FALSE); 
  3387. IF myErr <> noErr THEN DoError(myErr);    
  3388.  
  3389. The code in Listing 6-3 creates an entry for all required Apple events in the
  3390. Apple event dispatch table. The first entry creates an entry for the Open
  3391. Application event. The entry indicates the event class and event ID of the Open
  3392. Application event, the address of the handler for that event, and specifies 0 as
  3393. the reference constant. This entry is installed into the application’s Apple
  3394. event dispatch table.
  3395.  
  3396. The reference constant is passed to your handler by the Apple Event Manager each
  3397. time your handler is called. Your application can use this reference constant
  3398. for any purpose. If your application doesn’t use the reference constant, use 0
  3399. as the value. 
  3400.  
  3401. The last parameter to the AEInstallEventHandler function is a Boolean value that
  3402. determines whether the entry is added to the system Apple event dispatch table
  3403. or to your application’s Apple event dispatch table. To add the entry to your
  3404. application’s dispatch table, use FALSE as the value of this parameter. If you
  3405. specify TRUE, the entry is added to the system’s Apple event dispatch table.
  3406.  
  3407. If you add a handler to the system Apple event dispatch table, the handler that
  3408. you specify must reside in the system heap.
  3409.  
  3410.    Note: When an application calls a system Apple event handler, the A5 register
  3411.    is
  3412.    set up for the calling application. For this reason, if you provide a system
  3413.    Apple 
  3414.    event handler, it should never use A5 global variables or anything that
  3415.    depends 
  3416.    on a particular context; otherwise, the application that calls the system
  3417.    handler 
  3418.    may crash.
  3419.  
  3420. For any entry in your Apple event dispatch table, you can specify a wildcard
  3421. value for the event class, event ID, or both. You specify a wildcard by
  3422. supplying the typeWildCard constant when installing an entry into the Apple
  3423. event dispatch table. A wildcard value matches all possible values. 
  3424.  
  3425. For example, if you specify an entry with the typeWildCard event class and the
  3426. kAEOpenDocuments event ID, the Apple Event Manager dispatches Apple events of
  3427. any event class and an  event ID of kAEOpenDocuments to the handler for that
  3428. entry. 
  3429.  
  3430. If you specify an entry with the kCoreEventClass event class and the
  3431. typeWildCard event ID, the Apple Event Manager dispatches Apple events of the
  3432. kCoreEventClass event class and any event ID to the handler for that entry. 
  3433.  
  3434. If you specify an entry with the typeWildCard event class and the typeWildCard
  3435. event ID, the Apple Event Manager dispatches all Apple events of any event class
  3436. and any event ID to the handler for that entry.
  3437.  
  3438. If the AEProcessAppleEvent function cannot find a handler for an Apple event in
  3439. either the application’s Apple event dispatch table or the system Apple event
  3440. dispatch table, it returns the result code errAEEventNotHandled to the Apple
  3441. event server. If the client is waiting for a reply, AESend also returns this
  3442. result code as its function result.
  3443.  
  3444. If your application supports the Edition Manager, you should also add entries to
  3445. your application’s Apple event dispatch table for the Apple events that your
  3446. application receives from the Edition Manager. Listing 6-4 shows how to add
  3447. entries for these Apple events to your application’s Apple event dispatch table.
  3448.  
  3449. ¿ Listing 6-4   Inserting entries for Apple events sent by the Edition Manager
  3450. into an application’s Apple event dispatch table
  3451.  
  3452. myErr := AEInstallEventHandler(sectionEventMsgClass, sectionReadMsgID, 
  3453.                                @MyHandleSectionReadEvent, 0, FALSE);
  3454. IF myErr <> noErr THEN DoError(myErr);
  3455. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  3456.                                sectionWriteMsgID, 
  3457.                                @MyHandleSectionWriteEvent, 0, FALSE);
  3458. IF myErr <> noErr THEN DoError(myErr);
  3459. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  3460.                                sectionScrollMsgID, 
  3461.                                @MyHandleSectionScrollEvent, 0, FALSE);
  3462. IF myErr <> noErr THEN DoError(myErr);
  3463.  
  3464. See “Handling Apple Events Sent by the Edition Manager” later in this chapter
  3465. for the parameters associated with these events. See the Edition Manager chapter
  3466. in this volume for information on how your application should respond to the
  3467. Apple events sent by the Edition Manager.
  3468. _______________________________________________________________________________
  3469.  
  3470. æKY Handling…the…Required…Apple…Events
  3471. æC »Handling the Required Apple Events                             The Apple Event Manager
  3472. _______________________________________________________________________________
  3473.  
  3474. This section describes the required Apple events—the Apple events your
  3475. application must support to be 7.0-friendly—and the descriptor types for all
  3476. parameters of the required Apple events. It also describes how to write the
  3477. handlers for these events, and it provides sample code.
  3478.  
  3479. To support the required Apple events, you must set the necessary flags in the
  3480. 'SIZE' resource of your application, install entries into your application’s
  3481. Apple event dispatch table, add code to the event loop of your application to
  3482. recognize high-level events, and call the AEProcessAppleEvent function, as
  3483. described in the preceding two sections. You must also write handlers to handle
  3484. each Apple event; this section describes how to write these handlers.
  3485.  
  3486. _______________________________________________________________________________
  3487.  
  3488. æKY Required…Apple…Events
  3489. æC »Required Apple Events                                          The Apple Event Manager
  3490. _______________________________________________________________________________
  3491.  
  3492. When a user opens or prints a file from the Finder, the Finder sets up the
  3493. information your application can use to determine which files to open or print.
  3494. In version 7.0, if your application supports high-level events, the Finder
  3495. communicates this information to your application through the required Apple
  3496. events. 
  3497.  
  3498. The Finder sends one of the required Apple events to your application to request
  3499. that it open or print a list of documents, inform it that the Finder has just
  3500. opened your application, or inform it that the Finder is about to terminate your
  3501. application.
  3502.  
  3503. These are the required Apple events.
  3504.  
  3505.    Apple event                       Requested action
  3506.  
  3507.    Open Application             Perform tasks associated with opening your
  3508.    application 
  3509.  
  3510.    Open Documents              Open the specified documents 
  3511.  
  3512.    Print Documents               Print the specified documents
  3513.  
  3514.    Quit Application               Perform tasks—such as releasing memory,
  3515.    requesting 
  3516.                                                  the user to save documents, and
  3517.                                                  so on—associated with 
  3518.                                                  quitting; the Finder sends this
  3519.                                                  event to an application 
  3520.                                                  immediately after sending it a
  3521.                                                  Print Documents event or
  3522.                                                  if the user chooses Restart or
  3523.                                                  Shut Down from the 
  3524.                                                  Finder’s Special menu. 
  3525.  
  3526. The Finder uses the required Apple events as part of the new mechanisms in
  3527. system software version 7.0 for launching and terminating applications. This new
  3528. method of communicating Finder information to your application replaces the
  3529. mechanisms used in earlier versions of system software.
  3530.  
  3531. Applications that do not support high-level events can still use the
  3532. CountAppFiles, GetAppFiles, and ClrAppFiles procedures (or the GetAppParms
  3533. procedure) to get the Finder information. See the Segment Loader chapter of
  3534. Volume II for information on these routines. To make your application
  3535. 7.0-friendly and compatible with earlier versions of system software, it must
  3536. support both the old and new mechanisms.
  3537.  
  3538. Use the Gestalt function to determine whether the Apple Event Manager is
  3539. present. If it is and the isHighLevelEventAware flag is set in your
  3540. application’s 'SIZE' resource, your application receives the Finder information
  3541. through the required Apple events. 
  3542.  
  3543. If your application accepts high-level events, the Finder sends it an Open
  3544. Application, Open Documents, or Print Documents event immediately after
  3545. launching your application. Upon receiving any of these events, your application
  3546. should perform the action requested by the event.
  3547.  
  3548.    Note: This section describes the required Apple events as they are sent by
  3549.    the 
  3550.    Finder. When sent by other applications or processes, these same Apple 
  3551.    events—which are among the core Apple events described in the Apple Event 
  3552.    Registry—can include optional parameters not listed here. To be 7.0-friendly,
  3553.  
  3554.    your application only needs to handle the required parameters that are
  3555.    described 
  3556.    in this section.
  3557.  
  3558. Open Application—perform tasks associated with opening an application 
  3559.  
  3560. Event class                  kCoreEventClass
  3561.  
  3562. Event ID                      kAEOpenApplication
  3563.  
  3564. Parameters                  None
  3565.  
  3566. Requested action        Perform any tasks—such as opening an untitled document 
  3567.                                         window—that you would normally perform
  3568.                                         when a user 
  3569.                                         opens your application.
  3570.  
  3571. Open Documents—open the specified documents
  3572.  
  3573. Event class                    kCoreEventClass
  3574.  
  3575. Event ID                         kAEOpenDocuments
  3576.  
  3577. Required parameter    Keyword:                    keyDirectObject
  3578.                                          Descriptor type:         typeAEList
  3579.                                          Data:                            A list
  3580.                                          of alias records for the documents
  3581.                                                                               to
  3582.                                                                               be
  3583.  
  3584.  
  3585.  
  3586. Requested action          Open the documents specified in the keyDirectObject 
  3587.                                          parameter.
  3588.  
  3589. Print Documents—print the specified documents
  3590.  
  3591. Event class                     kCoreEventClass
  3592.  
  3593. Event ID                         kAEPrintDocuments
  3594.  
  3595. Required parameter    Keyword:                   keyDirectObject
  3596.                                          Descriptor type:        typeAEList
  3597.                                          Data:                           A list
  3598.                                          of alias records for the documents  
  3599.                                                                               to
  3600.  
  3601.  
  3602.  
  3603. Requested action         Print the documents specified in the keyDirectObject 
  3604.                                          parameter without opening windows for
  3605.                                          the documents. 
  3606.                                          The documents should remain open
  3607.                                          afterward.
  3608.  
  3609. Quit Application—perform tasks associated with quitting
  3610.  
  3611. Event class                      kCoreEventClass
  3612.  
  3613. Event ID                          kAEQuitApplication
  3614.  
  3615. Parameters                      None
  3616.  
  3617. Requested action           Perform any tasks that your application would
  3618. normally 
  3619.                                           perform when the user chooses Quit.
  3620.                                           Such tasks typically 
  3621.                                           include asking the user if he or she
  3622.                                           wants to save
  3623.                                           documents that have been changed. The
  3624.                                           Finder sends this 
  3625.                                           event to an application immediately
  3626.                                           after sending it a Print 
  3627.                                           Documents event or if the user chooses
  3628.                                           Restart or Shut 
  3629.                                           Down from the Finder’s Special menu.
  3630.  
  3631. Your application needs to recognize only two descriptor types to handle the
  3632. required Apple events:  descriptor lists and alias records. The Open Documents
  3633. event and Print Documents event use descriptor lists to store a list of
  3634. documents to open. Each document is specified as an alias record in the
  3635. descriptor list. 
  3636.  
  3637. You can retrieve the data that specifies the document to open as an alias
  3638. record, or you can request that the Apple Event Manager coerce the alias record
  3639. to a file system specification (FSSpec) record. The file system specification
  3640. record provides a standard method of identifying files in version 7.0. See the
  3641. File Manager chapter in this volume for a complete description of how to specify
  3642. files using file system specification records.
  3643. _______________________________________________________________________________
  3644.  
  3645. æKY Handling…the…Open…Application…Event
  3646. æC »Handling the Open Application Event                            The Apple Event Manager
  3647. _______________________________________________________________________________
  3648.  
  3649. To handle the Open Application event, your application should do just what it
  3650. does when the user opens your application. For example, your application might
  3651. open a new untitled document window in response to an Open Application event.
  3652.  
  3653. Listing 6-5 shows a handler that processes the Open Application event. The Open
  3654. Application event does not have any required parameters. This handler first
  3655. calls an application-defined function called MyGotRequiredParams. This function
  3656. checks whether the Apple event contains any required parameters. By definition,
  3657. the Open Application event should not contain any required parameters so, if the
  3658. Apple event does contain any, the handler returns an error. Otherwise the
  3659. handler opens a new document window.
  3660.  
  3661. ¿ Listing 6-5   A handler for the Open Application event
  3662.  
  3663. FUNCTION MyHandleOApp (theAppleEvent, reply: AppleEvent; 
  3664.                 handlerRefcon: LongInt) : OSErr;
  3665. VAR
  3666.    myErr: OSErr;
  3667. BEGIN
  3668.    myErr := MyGotRequiredParams (theAppleEvent);
  3669.    IF myErr <> noErr THEN
  3670.       MyHandleOApp := myErr
  3671.    ELSE
  3672.    BEGIN
  3673.       DoNew;
  3674.       MyHandleOApp := noErr;
  3675.    END;
  3676. END;
  3677.  
  3678. The MyGotRequiredParams function checks that all required parameters have been
  3679. extracted from the Apple event. See Listing 6-11 in “Writing Apple Event
  3680. Handlers” later in this chapter for a description of the MyGotRequiredParams
  3681. function.
  3682. _______________________________________________________________________________
  3683.  
  3684. æKY Handling…the…Open…Documents…Event
  3685. æC »Handling the Open Documents Event                              The Apple Event Manager
  3686. _______________________________________________________________________________
  3687.  
  3688. To handle the Open Documents event, your application should open the documents
  3689. specified in the Apple event. The Open Documents event contains a list of
  3690. documents to open in its direct parameter. Your application extracts this
  3691. information and then opens the specified documents.
  3692.  
  3693. Listing 6-6 shows a handler for the Open Documents event. The handler
  3694. illustrates how to open the documents referred to in the direct parameter.
  3695.  
  3696. ¿ Listing 6-6   A handler for the Open Documents event
  3697.  
  3698. FUNCTION MyHandleODoc (theAppleEvent, reply: AppleEvent;
  3699.                        handlerRefcon: LongInt) : OSErr;
  3700. VAR
  3701.    myFSS:               FSSpec;
  3702.    docList:             AEDescList;
  3703.    myErr:               OSErr;
  3704.    index, itemsInList:  LongInt;
  3705.    actualSize:          Size;
  3706.    keywd:               AEKeyword;
  3707.    returnedType:        DescType;
  3708. BEGIN
  3709.    {get the direct parameter--a descriptor list--and put it into docList}
  3710.    myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  3711.                            docList);
  3712.    IF myErr <> noErr THEN DoError(myErr);
  3713.    {check for missing required parameters}
  3714.    myErr := MyGotRequiredParams(theAppleEvent);
  3715.    IF myErr <> noErr THEN     {an error occurred}
  3716.       BEGIN                   {do the necessary error handling}
  3717.          MyHandleODoc := myErr;
  3718.          Exit (MyHandleODoc);
  3719.       END;
  3720.    {count the number of descriptor records in the list}
  3721.    myErr := AECountItems (docList, itemsInList);
  3722.    {now get each descriptor record from the list, get the alias record }
  3723.    { out of it, and open the associated file}
  3724.    FOR index := 1 TO itemsInList DO
  3725.        BEGIN
  3726.           myErr := AEGetNthPtr(docList, index, typeFSS, keywd, 
  3727.                                returnedType, @myFSS, Sizeof(myFSS), 
  3728.                                actualSize);
  3729.           IF myErr <> noErr THEN DoError(myErr);
  3730.           myErr := MyOpenFile(@myFSS);
  3731.           IF myErr <> noErr THEN DoError(myErr);
  3732.        END;
  3733.    myErr := AEDisposeDesc(docList);
  3734.    MyHandleODoc := noErr;
  3735. END;
  3736.  
  3737. The handler in Listing 6-6 first uses the AEGetParamDesc function to get the
  3738. direct parameter (specified by the keyDirectObject keyword) out of the Apple
  3739. event. The handler requests that AEGetParamDesc return a descriptor list in the
  3740. docList variable. The handler then checks to make sure that it has retrieved all
  3741. of the required parameters by calling the MyGotRequiredParams function (see
  3742. Listing 6-11 for a description of this routine).
  3743.  
  3744. Once the handler has retrieved the descriptor list from the Apple event, it uses
  3745. AECountItems to count the number of descriptors in the list. Using the returned
  3746. number as an index, the handler can get the data of each descriptor record in
  3747. the list. This handler requests that the AEGetNthPtr function coerce the data in
  3748. the descriptor record to a file system specification record. The handler can
  3749. then use the file system specification record as a parameter to its own routine
  3750. for opening files.
  3751.  
  3752. For more information on the AEGetParamDesc function, see “Getting Data out of
  3753. Parameters” later in this chapter. Also see “Getting Data out of Descriptor
  3754. Lists” for further information on the AEGetNthPtr and AECountItems functions.
  3755.  
  3756. After extracting the file system specification record that describes the
  3757. document to open, your application can use this record to open the file. For
  3758. example, in Listing 6-6, the code passes the file system specification record to
  3759. its routine for opening files, the MyOpenFile function. 
  3760.  
  3761. The MyOpenFile function is designed so that it can be called both in response to
  3762. the Open Documents event and to events generated by the user. For example, when
  3763. the user chooses Open from the File menu, the code that handles the mouse-down
  3764. event uses the StandardGetFile procedure to let the user choose a file; it then
  3765. calls MyOpenFile, passing the file system specification record returned by
  3766. StandardGetFile. By isolating code that performs a requested action from code
  3767. that interacts with the user, you can easily adapt your application to handle
  3768. Apple events that request the same action. 
  3769.  
  3770. Note that your handler should use the AEDisposeDesc function to dispose of the
  3771. descriptor list when your handler no longer requires the data in it. Your
  3772. handler should also return a result code.
  3773. _______________________________________________________________________________
  3774.  
  3775. æKY Handling…the…Print…Documents…Event
  3776. æC »Handling the Print Documents Event                             The Apple Event Manager
  3777. _______________________________________________________________________________
  3778.  
  3779. To handle the Print Documents event, your application should print the documents
  3780. specified in the Apple event. The Print Documents event contains a list of
  3781. documents to print in its direct parameter. Your application extracts this
  3782. information and then prints the specified documents. Your application should not
  3783. open any windows for the documents. Also note that your application should
  3784. remain open after processing the Print Documents event; the Finder sends your
  3785. application a Quit Application event immediately after sending it a Print
  3786. Documents event.
  3787.  
  3788. Listing 6-7 shows a handler for the Print Documents event. This handler is
  3789. similar to the handler for the Open Documents event. The code illustrates how to
  3790. print the documents referred to in the direct parameter.
  3791.  
  3792. ¿ Listing 6-7   A handler for the Print Documents event
  3793.  
  3794. FUNCTION MyHandlePDoc (theAppleEvent, reply: AppleEvent;
  3795.                        handlerRefcon: LongInt) : OSErr;
  3796. VAR
  3797.    myFSS:               FSSpec;
  3798.    docList:             AEDescList;
  3799.    myErr:               OSErr;
  3800.    index, itemsInList:  LongInt;
  3801.    actualSize:          Size;
  3802.    keywd:               AEKeyword;
  3803.    returnedType:        DescType;
  3804. BEGIN
  3805.    {get the direct parameter--a descriptor list--and put it into docList}
  3806.    myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  3807.                            docList);
  3808.    IF myErr <> noErr THEN DoError(myErr);
  3809.       {check for missing required parameters}
  3810.       myErr := MyGotRequiredParams(theAppleEvent);
  3811.    IF myErr <> noErr THEN {an error occurred}
  3812.       BEGIN
  3813.          {do the necessary error handling}
  3814.          MyHandlePDoc := myErr;
  3815.          Exit(MyHandlePDoc);
  3816.       END;
  3817.    {count the number of descriptor records in the list}
  3818.    myErr := AECountItems (docList, itemsInList);
  3819.    {now get each descriptor record from the list, get the alias record }
  3820.    { out of  it, and print the associated file}
  3821.    FOR index := 1 TO itemsInList DO
  3822.        BEGIN
  3823.        myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType,
  3824.                             @myFSS, Sizeof(myFSS), actualSize);
  3825.        IF myErr <> noErr THEN DoError(myErr);
  3826.        MyPrintFile(@myFSS);
  3827.        END;
  3828.    myErr := AEDisposeDesc(docList);
  3829.    MyHandlePDoc := noErr;
  3830. END;
  3831. _______________________________________________________________________________
  3832.  
  3833. æKY Handling…the…Quit…Application…Event
  3834. æC »Handling the Quit Application Event                            The Apple Event Manager
  3835. _______________________________________________________________________________
  3836.  
  3837. To handle the Quit Application event, your application should take any actions
  3838. that are necessary before it is terminated (such as saving any open documents).
  3839. Listing 6-8 shows an example of a handler for the Quit Application event.
  3840.  
  3841. The Finder sends your application a Quit Application event immediately after a
  3842. Print Documents event. The Finder also sends your application a Quit Application
  3843. event if the user chooses Restart or Shut Down from the Finder’s Special menu. 
  3844.  
  3845. ¿ Listing 6-8   A handler for the Quit Application event
  3846.  
  3847. FUNCTION MyHandleQuit (theAppleEvent, reply: AppleEvent;
  3848.                        handlerRefcon: LongInt) : OSErr;
  3849. VAR
  3850.    userCanceled : Boolean;
  3851. BEGIN
  3852.    {check for missing required parameters}
  3853.    myErr := MyGotRequiredParams (theAppleEvent);
  3854.    IF myErr <> noErr THEN {an error occurred}
  3855.       BEGIN
  3856.          {do the necessary error handling}
  3857.          MyHandleQuit := myErr;
  3858.          Exit (MyHandleQuit);
  3859.       END;
  3860.    userCanceled := MyPrepareToTerminate;
  3861.    IF userCanceled THEN
  3862.       MyHandleQuit := userCanceledErr
  3863.    ELSE
  3864.       MyHandleQuit := noErr;
  3865. END;
  3866.  
  3867. The handler in Listing 6-8 calls another function supplied by the application,
  3868. the MyPrepareToTerminate function. This function saves the documents for any
  3869. open windows and returns a Boolean value that indicates whether the Quit request
  3870. was canceled by the user. This is another example of isolating code for
  3871. interacting with the user from the code that performs the requested action.
  3872. Structuring your application in this way allows your application to use the same
  3873. routine when responding to a user event (such as choosing the Quit command from
  3874. the File menu) or to the corresponding Apple event. (For a description of the
  3875. MyGotRequiredParams function, see “Writing Apple Event Handlers” later in this
  3876. chapter.)
  3877.  
  3878. Note that your handler must not call the ExitToShell procedure. In Listing 6-8,
  3879. the application calls the ExitToShell procedure only if the handler returns
  3880. noErr as its function result.
  3881. _______________________________________________________________________________
  3882.  
  3883. æKY Handling…Apple…Events…Sent…by…the…Edition…Manager
  3884. æC »Handling Apple Events Sent by the Edition Manager              The Apple Event Manager
  3885. _______________________________________________________________________________
  3886.  
  3887. If your application provides publish and subscribe capabilities, it should
  3888. handle the Apple events sent by the Edition Manager in addition to the required
  3889. Apple events. Your application should also handle the Create Publisher event.
  3890. The Create Publisher event is described in the next section.
  3891.  
  3892. The Edition Manager sends your application Apple events to communicate
  3893. information about the publishers and subscribers in your application’s
  3894. documents. Specifically, the Edition Manager uses Apple events to notify your
  3895. application 
  3896.  
  3897.   • when the information in an edition is updated
  3898.  
  3899.   • when your application needs to write the data from a publisher to an edition
  3900.  
  3901.   • when your application should locate a particular publisher and scroll the 
  3902.      document to that location
  3903.  
  3904. The Apple events sent by the Edition Manager to your application are the Section
  3905. Read event, Section Write event, and Section Scroll event.
  3906.  
  3907. Section Read—read information into the specified section
  3908.  
  3909. Event class                     SectionEventMsgClass
  3910.  
  3911. Event ID                         SectionReadMsgID
  3912.  
  3913. Required parameter    Keyword:                keyDirectObject
  3914.                                          descriptor type:      typeSectionH
  3915.                                          Data:                         A handle
  3916.                                          to the section record of the 
  3917.  
  3918.                                                                            whose
  3919.  
  3920.  
  3921.  
  3922.  
  3923.  
  3924.  
  3925.  
  3926. Requested action          Update the subscriber with the new information from
  3927. the 
  3928.                                          edition.
  3929.  
  3930. Section Write—write the specified section to an edition
  3931.  
  3932. Event class                       SectionEventMsgClass
  3933.  
  3934. Event ID                           SectionWriteMsgID
  3935.  
  3936. Required parameter      Keyword:                keyDirectObject
  3937.                                            descriptor type:      typeSectionH
  3938.                                            Data:                         A
  3939.                                            handle to the section record of the 
  3940.  
  3941.  
  3942.  
  3943. Requested action           Write the publisher’s data to its edition.
  3944.  
  3945. Section Scroll—scroll the document to the specified section
  3946.  
  3947. Event class                       SectionEventMsgClass
  3948.  
  3949. Event ID                           SectionScrollMsgIDi.SectionScrollMsgID event
  3950. ID  6-;
  3951.  
  3952. Required parameter      Keyword:                 keyDirectObject
  3953.                                            descriptor type:       typeSectionH
  3954.                                            Data:                          A
  3955.                                            handle to the section record of the 
  3956.  
  3957.                                                                               to
  3958.  
  3959.  
  3960.  
  3961.  
  3962. Requested action           Scroll the document to the publisher identified by
  3963. the 
  3964.                                            specified section record. 
  3965.  
  3966. See the Edition Manager chapter in this volume for details on how your
  3967. application should respond to these events.
  3968. _______________________________________________________________________________
  3969.  
  3970. æKY Handling…the…Create…Publisher…Event
  3971. æC »Handling the Create Publisher Event                            The Apple Event Manager
  3972. _______________________________________________________________________________
  3973.  
  3974. If your application supports publish and subscribe capabilities, it should also
  3975. handle the Create Publisher event.
  3976.  
  3977. Create Publisher—create a publisher
  3978.  
  3979. Event class                       kAEMiscStdSuite
  3980.  
  3981. Event ID                           kAECreatePublisher
  3982.  
  3983. Required parameter       none
  3984.  
  3985. Optional parameter        Keyword:                keyDirectObject
  3986.                                              descriptor type:
  3987.                                              typeObjectSpecifier
  3988.                                              Data:                       The
  3989.                                              part of the document to publish. If
  3990.  
  3991.  
  3992.  
  3993.                                                                               is
  3994.  
  3995.  
  3996.  
  3997.  
  3998.  
  3999.  
  4000.  
  4001.  
  4002. Optional parameter        Keyword:                keyAEEditionFileLoc
  4003.                                             descriptor type:      typeAlias
  4004.                                             Data:                         An
  4005.                                             alias record that contains the 
  4006.  
  4007.  
  4008.  
  4009.  
  4010.  
  4011.  
  4012.  
  4013.  
  4014.  
  4015.  
  4016.  
  4017.  
  4018.  
  4019.  
  4020.  
  4021.  
  4022.  
  4023.  
  4024.  
  4025.  
  4026.  
  4027. Requested action             Create a publisher for the specified data using the
  4028. specified 
  4029.                                              location for the edition container.
  4030.                                              If the data isn’t specified,
  4031.                                              publish the current selection. If
  4032.                                              the location of the edition 
  4033.                                               isn’t specified, use the default
  4034.                                               location.
  4035.  
  4036. When your application receives the Create Publisher event, it should create a
  4037. publisher by writing the publisher's data to an edition. The data of the
  4038. publisher, and the location and name of the edition, are defined by the Apple
  4039. event. If the Create Publisher event includes a keyDirectObject parameter, then
  4040. your application should publish the data contained in the parameter. If the
  4041. keyDirectObject parameter is missing, then your application should publish the
  4042. current selection. If the document doesn’t have a current selection, your
  4043. handler for the event should return a non-zero result code.
  4044.  
  4045. If the Create Publisher event includes a keyAEEditionFileLoc parameter, then
  4046. your application should use the location and name contained in the parameter as
  4047. the default location and name of the edition. If the keyAEEditionFileLoc
  4048. parameter is missing, then your application should use the default location and
  4049. name your application normally uses to specify the edition container.
  4050.  
  4051. Listing 6-9 shows a handler for the Create Publisher event. This handler checks
  4052. for the keyDirectObject parameter and the keyAEEditionFileLoc parameter. If
  4053. either of these are not specified, the handler uses default values. The handler
  4054. uses the DoNewPublisher function, an application-defined function, to create the
  4055. publisher and its edition, create a section record, and update other data
  4056. structures associated with the document. See Listing 4-4 in the Edition Manager
  4057. chapter for an example of the DoNewPublisher function.
  4058.  
  4059. Note that the handler uses the AEInteractWithUser function to determine if user
  4060. interaction is allowed. If user interaction is allowed, the handler sets the
  4061. promptForDialog variable to TRUE, indicating that the DoNewPublisher function
  4062. should display the publisher dialog box. If user interaction is not allowed, the
  4063. handler sets the promptForDialog variable to FALSE, and the DoNewPublisher
  4064. function does not prompt the user for the location or name of the edition.
  4065.  
  4066. ¿ Listing 6-9   Handler for the Create Publisher event
  4067.  
  4068. FUNCTION MyHandleCreatePublisherEvent(theAppleEvent, reply: AppleEvent; 
  4069.                                       handlerRefcon: LongInt) : OSErr;
  4070. VAR
  4071. myErr:                  OSErr;
  4072. returnedType:           DescType;
  4073. thePublisherDataDesc:   AEDesc;
  4074. actualSize:             LongInt;
  4075. promptForDialog:        Boolean;
  4076. thisDocument:           MyDocumentInfoPtr;
  4077. preview:                Handle; 
  4078. previewFormat:          FormatType; 
  4079. defaultLocation:        EditionContainerSpec;
  4080.  
  4081. BEGIN
  4082.    MyGetDocumentPtr(thisDocument);
  4083.    myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, 
  4084.                            typeObjectSpecifier, thePublisherDataDesc);
  4085.    CASE myErr OF
  4086.         errAEDescNotFound: 
  4087.         BEGIN
  4088.            {use the current selection as the publisher }
  4089.            { set up info for later when DoNewPublisher displays preview}
  4090.            preview := MyGetPreviewForSelection(thisDocument);
  4091.            previewFormat := 'TEXT';
  4092.         END
  4093.         noErr: 
  4094.            {Use the data in keyDirectObject parameter as the publisher }
  4095.            { (which is returned in thePublisherDataDesc variable) }
  4096.            { set up info for later when DoNewPublisher displays preview}
  4097.            MySetInfoForPreview(thePublisherDataDesc, thisDocument, 
  4098.                                preview, previewFormat);
  4099.         OTHERWISE
  4100.             DoError(myErr);
  4101.    END;
  4102.    myErr := AEGetParamPtr(theAppleEvent, keyAEEditionFileLoc, 
  4103.                           typeFSS, returnedType, 
  4104.                           @defaultLocation.theFile,
  4105.                           SizeOf(FSSpec), actualSize);
  4106.    CASE myErr OF
  4107.       errAEDescNotFound: 
  4108.          {use the default location as the edition container}
  4109.               myErr := MyGetDefaultEditionSpec(thisDocument, 
  4110.                                                defaultLocation);
  4111.       noErr: 
  4112.       BEGIN       {The keyAEEditionFileLoc parameter }
  4113.                   { contained a default location}
  4114.          defaultLocation.thePart := kPartsNotUsed;
  4115.          defaultLocation.theFileScript := smSystemScript;
  4116.       END
  4117.       OTHERWISE
  4118.          DoError(myErr);
  4119.       END;
  4120.    myErr := MyGotRequiredParams(theAppleEvent);
  4121.    IF myErr <> noErr THEN
  4122.       BEGIN
  4123.       {handle the error appropriately}
  4124.       MyHandleCreatePublisherEvent := myErr;
  4125.       END;
  4126.    promptForDialog := (AEInteractWithUser(kAEDefaultTimeout, NIL,
  4127.                                           @MyIdleFunction) = noErr);  
  4128.    myErr := DoNewPublisher(thisDocument, promptForDialog, 
  4129.                            preview, previewFormat, defaultLocation);
  4130.    {add keyErrorNumber and keyErrorString parameters if desired}
  4131.    MyHandleCreatePublisherEvent := myErr;
  4132. END;
  4133. _______________________________________________________________________________
  4134.  
  4135. æKY Getting…Data…out…of…an…Apple…Event
  4136. æC »Getting Data out of an Apple Event                             The Apple Event Manager
  4137. _______________________________________________________________________________
  4138.  
  4139. The Apple Event Manager stores the parameters and attributes of an Apple event
  4140. in a format that is internal to the Apple Event Manager. You use Apple Event
  4141. Manager functions to retrieve the data from an Apple event and return it to your
  4142. application in a format your application can use.
  4143.  
  4144. The Apple Event Manager provides functions that retrieve data from parameters
  4145. and attributes. Most of these functions are available in two forms: one that
  4146. returns the desired data in a specified buffer and one that returns a descriptor
  4147. record containing the same data. For example, the AEGetParamPtr function returns
  4148. the data of a specified parameter, and the AEGetParamDesc function returns the
  4149. descriptor record of a specified parameter. 
  4150.  
  4151. You can also use Apple Event Manager functions to get data out of descriptor
  4152. records, descriptor lists, and AE records. You use similar functions to put data
  4153. into descriptor records, descriptor lists, and AE records.
  4154.  
  4155. When your handler receives an Apple event, you’ll typically use the
  4156. AEGetParamPtr, AEGetAttrPtr, AEGetParamDesc, or AEGetAttrDesc function to get
  4157. the data out of the Apple event.
  4158.  
  4159. Some Apple Event Manager functions let your application request that the data be
  4160. returned using any descriptor type, even if it is different from the original
  4161. descriptor type. If the original data is of a different descriptor type, the
  4162. Apple Event Manager attempts to coerce the data to the requested descriptor
  4163. type.
  4164.  
  4165. For example, the AEGetParamPtr function lets you specify the desired descriptor
  4166. type of the resulting data.
  4167.  
  4168. VAR
  4169. theAppleEvent:   AppleEvent;
  4170. returnedType:    DescType;
  4171. multResult:      LongInt;
  4172. actualSize:      Size;
  4173. myErr:           OSErr;
  4174.  
  4175. myErr := AEGetParamPtr(theAppleEvent, keyMultResult, typeLongInteger, 
  4176.                        returnedType, @multResult, SizeOf(multResult), 
  4177.                        actualSize);
  4178.  
  4179. In this example, the desired type is specified in the third parameter by the
  4180. typeLongInteger descriptor type. This requests that the Apple Event Manager
  4181. coerce the data to the type defined by this descriptor type (a long integer) if
  4182. it is not already of this type. 
  4183.  
  4184. To ensure that no coercion is performed and that the descriptor type of the
  4185. result is of the same type as the original, you can specify typeWildCard for the
  4186. desired descriptor type.
  4187.  
  4188. The Apple Event Manager returns the descriptor type of the resulting data in the
  4189. fourth parameter. This is useful information when you specify typeWildCard as
  4190. the desired descriptor type; you can determine the descriptor type of the
  4191. resulting data by examining the fourth parameter.
  4192.  
  4193. The Apple Event Manager can coerce many different types of data into another.
  4194. For example, the Apple Event Manager can convert alias records to file system
  4195. specification records, integers to Boolean data types, and characters to numeric
  4196. data types, in addition to other data type conversions.
  4197.  
  4198. You can also provide your own coercion handlers to coerce other data types. See
  4199. “Writing and Installing Coercion Handlers” later in this chapter for information
  4200. on the coercion provided by the Apple Event Manager and how to provide your own
  4201. coercion handlers.
  4202.  
  4203. Parameters are keyword-specified descriptor records. You can use AEGetParamDesc
  4204. to get the descriptor record of a parameter, or you can use AEGetParamPtr to get
  4205. the data out of the descriptor record of a parameter. Attributes are also
  4206. keyword-specified descriptor records, and you can use similar routines to get
  4207. the descriptor record of an attribute or to get the data out of an attribute.
  4208.  
  4209. The following sections show examples of how to use the AEGetParamPtr,
  4210. AEGetAttrPtr, AEGetParamDesc, or AEGetAttrDesc function to get the data out of
  4211. an Apple event.
  4212. _______________________________________________________________________________
  4213.  
  4214. æKY Getting…Data…out…of…a…Parameter
  4215. æC »Getting Data out of a Parameter                                The Apple Event Manager
  4216. _______________________________________________________________________________
  4217.  
  4218. You can use the AEGetParamPtr or AEGetParamDesc function to get the data out of
  4219. a parameter. Use the AEGetParamPtr function to return the data contained in a
  4220. parameter. Use the AEGetParamDesc function when you need to get the descriptor
  4221. record of a parameter. You often use the AEGetParamDesc function to extract the
  4222. descriptor list from a parameter.
  4223.  
  4224. You can also use the AEGetKeyPtr function to return the data contained in a
  4225. parameter. The AEGetKeyPtr function provides an additional feature; you can use
  4226. this function to get data out of an AE record. See “Getting Data and
  4227. Keyword-Specified Descriptor Records From AE Records” later in this chapter for
  4228. information on this function.
  4229.  
  4230. For example, you use an Apple Event Manager function to get the data out of a
  4231. Section Read event. The Edition Manager sends your application a Section Read
  4232. event to tell your application to read updated information from an edition into
  4233. the specified subscriber. The direct parameter of the Apple event contains a
  4234. handle to the section record of the subscriber. You can use the AEGetParamPtr
  4235. function to get the data out of the Apple event.
  4236.  
  4237. You specify the Apple event that contains the desired parameter, the keyword of
  4238. the desired parameter, the descriptor type the function should use to return the
  4239. data, a buffer to store the data, and the size of this buffer as parameters to
  4240. the AEGetParamPtr function. The AEGetParamPtr function returns the descriptor
  4241. type of the resulting data and the actual size of the data, and it places the
  4242. requested data in the specified buffer.
  4243.  
  4244. VAR
  4245. SectionH:          sectionHandle;
  4246. theAppleEvent:     AppleEvent;
  4247. returnedType:      DescType;
  4248. actualSize:        Size;
  4249. myErr:             OSErr;
  4250.  
  4251. myErr := AEGetParamPtr(theAppleEvent, keyDirectObject, typeSectionH, 
  4252.                        returnedType, @sectionH, SizeOf(sectionH), 
  4253.                        actualSize);
  4254.  
  4255. In this example, the keyDirectObject keyword specifies that the AEGetParamPtr
  4256. function should extract information from the direct parameter; AEGetParamPtr
  4257. returns the data in the buffer specified by the sectionH variable. 
  4258.  
  4259. You can request that the Apple Event Manager return the data using the
  4260. descriptor type of the original data or you can request that the Apple Event
  4261. Manager coerce the data into a descriptor type that is different from the
  4262. original. You can specify the desired descriptor type as typeWildCard if you
  4263. don’t want any coercion performed—in which case, the AEGetParamPtr function
  4264. returns the original descriptor type of the parameter.
  4265.  
  4266. The typeSectionH descriptor type specifies that the returned data should be
  4267. coerced to a handle to a section record. In this example, the Apple Event
  4268. Manager automatically coerces the data from a temporary ID to a handle to a
  4269. section record when you specify the typeSectionH descriptor type. You can use
  4270. the information returned in the sectionH variable to identify the subscriber and
  4271. read in the information from the edition.
  4272.  
  4273. In this example, the AEGetParamPtr function returns in the returnedType variable
  4274. the descriptor type of the resulting data. In most cases, the descriptor type of
  4275. the resulting data matches the requested descriptor type, unless the Apple Event
  4276. Manager wasn’t able to coerce the data to the specified descriptor type. If the
  4277. coercion fails, the Apple Event Manager returns the errAECoercionFail result
  4278. code.
  4279.  
  4280. The AEGetParamPtr function returns the actual size of the data in the actualSize
  4281. variable. If the value returned in the actualSize variable is greater than the
  4282. amount your application allocated for the buffer to hold the returned data, your
  4283. application can increase the size of its buffer to this amount, and get the data
  4284. again. You can also choose to use the AEGetParamDesc function when your
  4285. application doesn’t know the size of the data.
  4286.  
  4287. You can use the AEGetParamDesc function to return the descriptor record of a
  4288. parameter. This function is useful, for example, when extracting descriptor
  4289. lists from a parameter.
  4290.  
  4291. You specify the Apple event that contains the desired parameter, the keyword of
  4292. the desired parameter, the descriptor type the function should use to return the
  4293. descriptor record, and a buffer to store the returned descriptor record as
  4294. parameters to the AEGetParamDesc function. The AEGetParamDesc function returns
  4295. the descriptor record using the specified descriptor type. 
  4296.  
  4297. For example, the direct parameter of the Open Documents event contains a
  4298. descriptor list that specifies the documents to open. You can use the
  4299. AEGetParamDesc function to get the descriptor list out of the direct parameter.
  4300.  
  4301. VAR
  4302. docList:           AEDescList;
  4303. theAppleEvent:     AppleEvent;
  4304. myErr:             OSErr;
  4305.  
  4306. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  4307.                         docList);
  4308.  
  4309. In this example, the Apple event specified by the variable theAppleEvent
  4310. contains the desired parameter. The keyDirectObject keyword specifies that the
  4311. AEGetParamDesc function should get the descriptor record of the direct
  4312. parameter. The typeAEList descriptor type specifies that the descriptor record
  4313. should be returned as a descriptor list. In this example, the AEGetParamDesc
  4314. function returns a descriptor list in the docList variable.
  4315.  
  4316. The descriptor list contains a list of descriptor records. To get the descriptor
  4317. records and their data out of a descriptor list, use the AECountItems function
  4318. to find the number of descriptor records in the list, and then make repetitive
  4319. calls to the AEGetNthPtr function to get the data out of each descriptor record.
  4320. See “Getting Data out of a Descriptor List” later in this chapter for more
  4321. information.
  4322.  
  4323. Note that the AEGetParamDesc function copies the descriptor record from the
  4324. parameter. When you’re done with a descriptor record that you obtained from
  4325. AEGetParamDesc, you must dispose of it by calling the AEDisposeDesc function.
  4326. _______________________________________________________________________________
  4327.  
  4328. æKY Getting…Data…out…of…an…Attribute
  4329. æC »Getting Data out of an Attribute                               The Apple Event Manager
  4330. _______________________________________________________________________________
  4331.  
  4332. You can use the AEGetAttributePtr or AEGetAttributeDesc function to get the data
  4333. out of the attributes of an Apple event.
  4334.  
  4335. You can get the data out of an attribute using the AEGetAttributePtr function.
  4336. You specify the Apple event that contains the desired attribute, the keyword of
  4337. the desired attribute, the descriptor type the function should use to return the
  4338. data, a buffer to store the data, and the size of this buffer as parameters to
  4339. the AEGetAttributePtr function. The AEGetAttributePtr function returns the
  4340. descriptor type of the returned data and the actual size of the data, and it
  4341. places the requested data in the specified buffer.
  4342.  
  4343. For example, this code gets the data out of the keyEventSourceAttr attribute of
  4344. an Apple event.
  4345.  
  4346. VAR
  4347. theAppleEvent:   AppleEvent;
  4348. returnedType:    DescType;
  4349. sourceOfAE:      Integer;
  4350. actualSize:      Size;
  4351. myErr:           OSErr;
  4352.  
  4353. myErr := AEGetAttributePtr(theAppleEvent, keyEventSourceAttr, 
  4354.                            typeShortInteger, returnedType, sourceOfAE,
  4355.                            SizeOf(sourceOfAE), actualSize);
  4356.  
  4357. The keyEventSourceAttr keyword specifies the attribute to get the data from. The
  4358. typeShortInteger descriptor type specifies that the data should be returned as a
  4359. short integer; the returnedType variable contains the actual descriptor type
  4360. that is returned. You also must specify a buffer to hold the returned data, and
  4361. specify the size of this buffer. The AEGetAttributePtr function returns the
  4362. actual size of the data returned in the actualSize variable. You can check this
  4363. value to make sure you got all the data.
  4364.  
  4365. As with the AEGetParamPtr function, you can request that AEGetAttributePtr
  4366. return the data using the descriptor type of the original data, or you can
  4367. request that the Apple Event Manager coerce the data into a descriptor type that
  4368. is different from the original. 
  4369.  
  4370. In this example, the AEGetAttributePtr function returns the requested data in
  4371. the sourceOfAE variable, and you can determine the source of the Apple event by
  4372. examining this value.
  4373.  
  4374. The next example shows how to use the AEGetAttributePtr function to get data out
  4375. of the keyMissedKeywordAttr attribute. After your handler extracts all known
  4376. parameters from an Apple event, it should check whether the keyMissedKeywordAttr
  4377. attribute exists. If it does, then your handler did not get all of the required
  4378. parameters.
  4379.  
  4380. Note that if AEGetAttributePtr returns the errAEDescNotFound result code, then
  4381. the keyMissedKeywordAttr does not exist—which indicates that your application
  4382. has extracted all of the required parameters. If AEGetAttributePtr returns
  4383. noErr, then the keyMissedKeywordAttr does exist—which indicates that your
  4384. handler did not get all of the required parameters.
  4385.  
  4386. myErr := AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, 
  4387.                            typeWildCard, returnedType, NIL, 0, 
  4388.                            actualSize);
  4389.  
  4390. The data in the keyMissedKeywordAttr attribute contains the first required
  4391. parameter, if any, that your handler didn’t retrieve. If you want this data
  4392. returned, specify a buffer to hold the data and specify the size of the buffer.
  4393. Otherwise, as in this example, specify NIL as the buffer and 0 as the size of
  4394. the buffer.
  4395. _______________________________________________________________________________
  4396.  
  4397. æKY Getting…Data…out…of…a…Descriptor…List
  4398. æC »Getting Data out of a Descriptor List                          The Apple Event Manager
  4399. _______________________________________________________________________________
  4400.  
  4401. You can use the AECountItems function to count the number of items in a
  4402. descriptor list, and you can use AEGetNthDesc or AEGetNthPtr to get a descriptor
  4403. record or its data out of a descriptor list.
  4404.  
  4405. The Open Documents event contains a direct parameter that specifies the list of
  4406. documents to open. The list of documents is contained in a descriptor list.
  4407. After extracting the descriptor list from the parameter, you can determine the
  4408. number of items in the list and then extract each descriptor record from the
  4409. descriptor list. See Figure 6-6 in “Data Structures Within Apple Events” earlier
  4410. in this chapter for a depiction of the Open Documents event.
  4411.  
  4412. For example, when your handler receives an Open Documents event, you can use the
  4413. AEGetParamDesc function to return the direct parameter as a descriptor list. You
  4414. can then use AECountItems to return the number of descriptor records in the
  4415. list.
  4416.  
  4417. VAR
  4418. theAppleEvent:    AppleEvent;
  4419. docList:          AEDescList;
  4420. itemsInList:      LongInt;
  4421. myErr:            OSErr;
  4422.  
  4423. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, 
  4424.                         docList);
  4425. myErr := AECountItems(docList, itemsInList);
  4426.  
  4427. The AEGetParamDesc function returns in the docList variable the descriptor list
  4428. from the direct parameter of the Open Documents event. You specify this list to
  4429. the AECountItems function.
  4430.  
  4431. You specify the descriptor list whose items you want to count in the first
  4432. parameter to AECountItems. The Apple Event Manager returns the number of items
  4433. in the list in the second parameter. When extracting the descriptor records from
  4434. a list, you often use the number of items as a loop index. Here’s an example:
  4435.  
  4436. FOR index := 1 TO itemsInList DO
  4437.    BEGIN
  4438.    {for each descriptor record in the list, get its data}
  4439.    END;
  4440.  
  4441. The format of the descriptor records in a descriptor list is private to the
  4442. Apple Event Manager. You must use the AEGetNthPtr or AEGetNthDesc function to
  4443. extract descriptor records from a descriptor list.
  4444.  
  4445. You specify the descriptor list that contains the desired descriptor records and
  4446. an index as parameters to the AEGetNthPtr function. The index represents a
  4447. specific descriptor record in the descriptor list. The AEGetNthPtr returns the
  4448. data from the descriptor record represented by the specified index. 
  4449.  
  4450. You also specify the descriptor type the function should use to return the data,
  4451. a buffer to store the data, and the size of this buffer. The AEGetNthPtr
  4452. function returns the keyword of the parameter, the descriptor type of the
  4453. returned data, and the actual size of the data, and it places the requested data
  4454. in the specified buffer.
  4455.  
  4456. Here’s an example that uses the AEGetNthPtr function to extract an item from the
  4457. descriptor list in the direct parameter of the Open Documents event. 
  4458.  
  4459. myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType,
  4460.                      @myFSS, Sizeof(myFSS), actualSize);
  4461.  
  4462. The docList variable specifies the descriptor list from the direct parameter of
  4463. the Open Documents event. The index variable specifies the index of the
  4464. descriptor record to extract. You can use the typeFSS descriptor type, as in
  4465. this example, to specify that the data be returned as a file system
  4466. specification record. The Apple Event Manager automatically coerces the original
  4467. data type of the descriptor record from an alias record to a file system
  4468. specification record. The AEGetNthPtr function returns the keyword of the
  4469. parameter in the keywd variable. The function returns in the returnedType
  4470. variable the descriptor type of the resulting data. 
  4471.  
  4472. You specify a buffer to hold the desired data and the size (in bytes) of the
  4473. buffer as parameters to the AEGetNthPtr function. In this example, the myFSS
  4474. variable specifies the buffer. The function returns the actual size of the data
  4475. in the actualSize variable. If this size is larger than the size of the buffer
  4476. you provided, you know that you didn’t get all of the data for the descriptor
  4477. record.
  4478.  
  4479. Listing 6-10 shows a more complete example of extracting the items from a
  4480. descriptor list in the Open Documents event.
  4481.  
  4482. ¿ Listing 6-10   Extracting items from a descriptor list
  4483.  
  4484. VAR
  4485. index:          LongInt;
  4486. itemsInList:    LongInt;
  4487. docList:        AEDescList;
  4488. keywd:          AEKeyword;
  4489. returnedType:   DescType;
  4490. myFSS:          FSSpec;
  4491. actualSize:     Size;
  4492. myErr:         OSErr;
  4493.  
  4494. FOR index := 1 TO itemsInList DO
  4495.     BEGIN
  4496.         myErr := AEGetNthPtr(docList, index, typeFSS, keywd, returnedType ,
  4497.                              @myFSS, Sizeof(myFSS), actualSize);
  4498.         IF myErr <> noErr THEN DoError(myErr);
  4499.         myErr := MyOpenFile(@myFSS);
  4500.         IF myErr <> noErr THEN DoError(myErr);
  4501.     END;
  4502.     myErr := AEDisposeDesc(docList); 
  4503. _______________________________________________________________________________
  4504.  
  4505. æKY Writing…Apple…Event…Handlers
  4506. æC »Writing Apple Event Handlers                                   The Apple Event Manager
  4507. _______________________________________________________________________________
  4508.  
  4509. For each Apple event your application supports, you must provide a function
  4510. called an Apple event handler. The AEProcessAppleEvent function calls one of
  4511. your Apple event handlers when it processes an Apple event. Your Apple event
  4512. handlers should perform any action requested by the Apple event, add parameters
  4513. to the reply Apple event if appropriate, and return a result code.
  4514.  
  4515. The Apple Event Manager uses dispatch tables to route Apple events to the
  4516. appropriate Apple event handler. You must supply an Apple event handler for each
  4517. entry in your application’s Apple event dispatch table. Each handler must be a
  4518. function that uses this syntax:
  4519.  
  4520. FUNCTION MyEventHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  4521.                          handlerRefcon: LongInt) : OSErr; 
  4522.  
  4523. The parameter theAppleEvent is the Apple event to handle. Your handler uses
  4524. Apple Event Manager functions to extract any parameters and attributes from the
  4525. Apple event and then performs the necessary processing. The reply parameter is
  4526. the default reply provided by the Apple Event Manager. (“Replying to an Apple
  4527. Event,” later in this chapter, describes how to add parameters to the default
  4528. reply.) The handlerRefcon parameter is the reference constant stored in the
  4529. Apple event dispatch table entry for the Apple event. Your handler can ignore
  4530. this parameter if your application does not use the reference constant.
  4531.  
  4532. After extracting all known parameters from the Apple event, every handler should
  4533. determine whether the Apple event contains any further required parameters. Your
  4534. handler can check that it retrieved all the required parameters by checking
  4535. whether the keyMissedKeywordAttr attribute exists. If the attribute exists, then
  4536. your handler has not retrieved all the required parameters. If additional
  4537. required parameters exist, then your handler should immediately return an error.
  4538. If the attribute does not exist, then the Apple event does not contain any more
  4539. required parameters. 
  4540.  
  4541. Listing 6-11 shows a function that checks for a keyMissedKeywordAttr attribute.
  4542. A handler calls this function after getting all the required parameters it knows
  4543. about from an Apple event.
  4544.  
  4545. ¿ Listing 6-11   A function that checks for a keyMissedKeywordAttr attribute
  4546.  
  4547. FUNCTION MyGotRequiredParams (theAppleEvent: AppleEvent) : OSErr;
  4548. VAR
  4549.    returnedType:   DescType;
  4550.    actualSize:     Size;
  4551.    myErr:          OSErr;
  4552. BEGIN
  4553.    myErr := AEGetAttributePtr (theAppleEvent, keyMissedKeywordAttr, 
  4554.                                typeWildCard, returnedType, NIL, 0, 
  4555.                                actualSize);
  4556.    IF myErr = errAEDescNotFound THEN  {you got all the required }
  4557.                                       { parameters}
  4558.       MyGotRequiredParams := noErr
  4559.    ELSE IF myErr = noErr THEN {you missed a required parameter}
  4560.       MyGotRequiredParams := errAEEventNotHandled
  4561.    ELSE {the call to AEGetAttributePtr failed}
  4562.       MyGotRequiredParams := myErr;
  4563.   END;
  4564.  
  4565. The code in Listing 6-11 uses the AEGetAttributePtr function to get the
  4566. keyMissedKeywordAttr attribute. This attribute contains the first required
  4567. parameter, if any, that your handler didn’t retrieve. If AEGetAttributePtr
  4568. returns the errAEDescNotFound result code, the Apple event doesn’t contain a
  4569. keyMissedKeywordAttr attribute. If the Apple event doesn’t contain this
  4570. attribute, then your handler has extracted all of the required parameters. 
  4571.  
  4572. If the AEGetAttributePtr function returns noErr as the result code, then the
  4573. attribute does exist, meaning that your handler has not extracted all of the
  4574. required parameters. In this case, your handler should return an error and not
  4575. process the Apple event.
  4576.  
  4577. The first remaining required parameter is specified by the data of the
  4578. keyMissedKeywordAttr attribute. If you want this data returned, specify a buffer
  4579. to hold the data. Otherwise, specify NIL as the buffer and 0 as the size of the
  4580. buffer. If you specify a buffer to hold the data, you can check the value of the
  4581. actualSize parameter to see if the data is larger than the buffer you allocated.
  4582. _______________________________________________________________________________
  4583.  
  4584. æKY Replying…to…an…Apple…Event
  4585. æC »Replying to an Apple Event                                     The Apple Event Manager
  4586. _______________________________________________________________________________
  4587.  
  4588. Your handler routine for a particular Apple event is responsible for performing
  4589. the action requested by the Apple event, and can optionally return data in a
  4590. reply Apple event. The Apple Event Manager passes a default reply Apple event to
  4591. your handler. The default reply Apple event has no parameters when it is passed
  4592. to your handler. Your handler can add parameters to the reply Apple event. If
  4593. the client application requested a reply, the Apple Event Manager returns the
  4594. reply Apple event to the client. 
  4595.  
  4596. The reply Apple event is identified by the kCoreEventClass event class and by
  4597. the kAEAnswer event ID.
  4598.  
  4599. When your handler finishes processing an Apple event, it returns a result code
  4600. to AEProcessAppleEvent. The AEProcessAppleEvent function returns this result
  4601. code as its function result. If your handler returns a nonzero result code, the
  4602. Apple Event Manager also returns this result code to the client application by
  4603. putting the result code into a keyErrorNumber parameter for the reply Apple
  4604. event. The client can check for the existence of this parameter to determine
  4605. whether the handler performed the requested action.
  4606.  
  4607. The client application specifies whether it wants a reply Apple event or not by
  4608. specifying flags (represented by constants) in the sendMode parameter of the
  4609. AESend function.
  4610.  
  4611. If the client specifies the kAEWaitReply flag in the sendMode parameter, the
  4612. AESend function does not return until the timeout expires or the server returns
  4613. a reply. When the server returns a reply, the reply parameter to AESend contains
  4614. the reply Apple event that your handler returned to the AEProcessAppleEvent
  4615. function.
  4616.  
  4617. If the client specified the kAEQueueReply flag, the client receives the reply
  4618. event in its normal processing of other events.
  4619.  
  4620. If the client specified the kAENoReply flag, your handler may return a reply
  4621. Apple event to AEProcessAppleEvent, but this reply is not returned to the
  4622. client.
  4623.  
  4624. Your handler routine should always set its function result to noErr if it
  4625. successfully handles the Apple event or to a nonzero result code if an error
  4626. occurs. The Apple Event Manager automatically adds any nonzero result code that
  4627. your handler returns to a keyErrorNumber parameter in the reply Apple event. In
  4628. addition to returning a result code, your handler can also return an error
  4629. string in the keyErrorString parameter of the reply Apple event. Your handler
  4630. should provide meaningful text in the keyErrorString parameter, so that the
  4631. client can display this string to the user if desired.
  4632.  
  4633. Listing 6-12 shows how to add the keyErrorString parameter to the reply Apple
  4634. event. See “Adding Parameters to an Apple Event” later in this chapter for a
  4635. description of the AEPutParamPtr function.
  4636.  
  4637. ¿ Listing 6-12   Adding the keyErrorString parameter to the reply Apple event
  4638.  
  4639. FUNCTION MyHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  4640.                     handlerRefcon: LongInt) : OSErr; 
  4641. VAR
  4642. myErr:   OSErr;
  4643. errStr:  Str255;
  4644. BEGIN
  4645.    {if an error occurs when handling an Apple event, set the }
  4646.    { function result and error string accordingly}
  4647. IF myErr <> noErr THEN
  4648.    BEGIN
  4649.    MyHandler := myErr;    {result code to be returned - the Apple Event }
  4650.                           { Manager adds this result code to the reply }
  4651.                           { Apple event as the keyErrorNumber parameter}
  4652.    {add error string parameter to the default reply}
  4653.    errStr := 'Reason why error occurred';
  4654.    myErr := AEPutParamPtr(reply, keyErrorString, typeChar, 
  4655.                           Ptr(@errStr[1]), length(errStr));
  4656.    Exit(MyHandler);
  4657.    END;
  4658. END;
  4659.  
  4660. If your handler needs to return data to the client, it can add parameters to the
  4661. reply Apple event. For example, Listing 6-13 shows how a handler for the
  4662. Multiply event (an imaginary Apple event that asks the server to multiply two
  4663. numbers) might return the results of the multiplication to the client.
  4664.  
  4665. ¿ Listing 6-13   Adding parameters to the reply Apple event
  4666.  
  4667. FUNCTION MyMultHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  4668.                         handlerRefcon: LongInt) : OSErr; 
  4669. VAR
  4670. myErr:               OSErr;
  4671. number1, number2:    LongInt;
  4672. replyResult:         LongInt;
  4673. actualSize:          Size;
  4674. returnedType:        DescType;
  4675. BEGIN
  4676.    {get the numbers to multiply from the parameters of the Apple event }
  4677.    { put the numbers in the number1 and number2 variables }
  4678.    { then perform the requested multiplication}
  4679. myErr := MyDoMultiply(theAppleEvent, number1, number2, replyResult);
  4680.  
  4681. {return the result of the multiplication in the reply Apple event}
  4682. IF myErr = noErr THEN
  4683.    BEGIN
  4684.    myErr := AEPutParamPtr(reply, keyDirectObject, typeLongInteger, 
  4685.                           @replyResult, SizeOf(replyResult));
  4686.    MyMultHandler := myErr;
  4687.    END;
  4688. {if an error occurs, set the function result and error string }
  4689. { accordingly, as shown in Listing 6-12}
  4690. END;
  4691. _______________________________________________________________________________
  4692.  
  4693. æKY Disposing…of…Apple…Event…Data…Structures
  4694. æC »Disposing of Apple Event Data Structures                       The Apple Event Manager
  4695. _______________________________________________________________________________
  4696.  
  4697. Whenever you use Apple Event Manager functions to create a descriptor record,
  4698. descriptor list, or Apple event record, the Apple Event Manager allocates memory
  4699. for these data structures. Likewise, when you extract a descriptor record by
  4700. using Apple Event Manager functions, the Apple Event Manager creates a copy of
  4701. the descriptor record for you to use.
  4702.  
  4703. Whenever you are done using a descriptor record or descriptor list that you have
  4704. created or extracted from an Apple event, you must dispose of the descriptor
  4705. record—and thereby deallocate the memory it uses—by calling the AEDisposeDesc
  4706. function.
  4707.  
  4708. Also, when you are done using the Apple event specified in the AESend function
  4709. and finished with the reply Apple event, you should dispose of their descriptor
  4710. records using the AEDisposeDesc function. You should dispose of them even if
  4711. AESend returns a nonzero result code.
  4712.  
  4713. Once you are done using them, you should dispose of any Apple event data
  4714. structures created or returned by these functions:
  4715.  
  4716.    AECreateAppleEvent                 AECreateList
  4717.    AEGetNthDesc                             AECreateDesc
  4718.    AEGetKeyDesc                              AEGetParamDesc
  4719.    AECoerceDesc                               AEGetAttributeDesc
  4720.    AECoercePtr                                  AEDuplicateDesc
  4721.    AEGetKeyDesc
  4722.  
  4723. Even if you add a descriptor record to an Apple event (for example, when you
  4724. create a descriptor record by calling AECreateDesc and then put a copy of it
  4725. into a parameter of an Apple event by calling AEPutParamDesc), you’re still
  4726. responsible for disposing of the original descriptor record.
  4727.  
  4728. In one case, the Apple Event Manager does take care of disposing of the Apple
  4729. event data structures for you: when your handler returns to AEProcessAppleEvent,
  4730. the Apple Event Manager disposes of the Apple event and the reply Apple event.
  4731. Note that your handler is still responsible for disposing of any Apple event
  4732. data structures created when extracting data from the Apple event. The Apple
  4733. event and reply Apple event that your handler receives are only copies of the
  4734. originals. The client application is responsible for disposing of the original
  4735. data structures.
  4736. _______________________________________________________________________________
  4737.  
  4738. æKY Interacting…With…the…User
  4739. æC »Interacting With the User                                      The Apple Event Manager
  4740. _______________________________________________________________________________
  4741.  
  4742. When your application receives an Apple event, it may need to interact with the
  4743. user. For example, your application may need to display a dialog box asking for
  4744. additional input or confirmation from the user. You must make sure that your
  4745. application is in the foreground before interacting with the user. To do this,
  4746. use the AEInteractWithUser function before actually interacting with the user.
  4747. The AEInteractWithUser function checks the user interaction preferences set by
  4748. the client application and the server application and, if user interaction is
  4749. allowed, brings your application to the front (either directly or by posting a
  4750. notification request) if it is not already in the front.
  4751.  
  4752. If both the client and server applications allow user interaction,
  4753. AEInteractWithUser usually posts a notification request; AEInteractWithUser
  4754. brings the server to the front after the user responds to the notification
  4755. request. The AEInteractWithUser function can also bring the server application
  4756. directly to the front—but only when doing so is in accordance with the principle
  4757. of user control and if the client allows it.
  4758.  
  4759. Both the client and server specify their preferences for user interaction: the
  4760. client specifies whether the server should be allowed to interact with the user,
  4761. and the server specifies when it will allow user interaction while processing an
  4762. Apple event. 
  4763.  
  4764. An application that sends an Apple event indicates its preferences for how the
  4765. server application should interact with the user by setting various flags in the
  4766. sendMode parameter to AESend. The Apple Event Manager translates these flags
  4767. into the corresponding flags in the keyInteractLevelAttr attribute of the Apple
  4768. event, and sets them.
  4769.  
  4770. The server application sets its preferences by using the AESetInteractionAllowed
  4771. function. This function lets your application specify whether it allows
  4772. interaction with the user as a result of receiving an Apple event from itself;
  4773. from itself and other processes on the local machine; or from itself, local
  4774. processes, and processes from another computer on the network.
  4775.  
  4776. Your application calls the AEInteractWithUser function before interacting with
  4777. the user. If AEInteractWithUser returns the noErr result code, then your
  4778. application is currently in the front and your application is free to interact
  4779. with the user. If AEInteractWithUser returns the errAENoUserInteraction result
  4780. code, then the conditions didn’t allow user interaction and your application
  4781. should not interact with the user. 
  4782.  
  4783. The client application sets user interaction preferences by setting flags in the
  4784. sendMode parameter to the AESend function. The Apple Event Manager automatically
  4785. adds the specified flags to the keyInteractLevelAttr attribute of the Apple
  4786. event. These flags are represented by constants and are described here.
  4787.  
  4788. Flag                                      Description
  4789.  
  4790. kAENeverInteract            The server application should never interact with
  4791. the 
  4792.                                               user in response to this Apple
  4793.                                               event. If this flag is set, 
  4794.                                               AEInteractWithUser does not bring
  4795.                                               the server application 
  4796.                                               to the foreground (this is the
  4797.                                               default when an Apple 
  4798.                                               event is sent to a remote
  4799.                                               application).
  4800.  
  4801. kAECanInteract                 The server application can interact with the user
  4802. in 
  4803.                                                response to this Apple event—by
  4804.                                                convention, if the user 
  4805.                                                needs to supply information to
  4806.                                                the server. If this flag is 
  4807.                                                set and the server allows
  4808.                                                interaction, 
  4809.                                                AEInteractWithUser brings the
  4810.                                                server application to the 
  4811.                                                foreground (this is the default
  4812.                                                when an Apple event is 
  4813.                                                sent to a local application).
  4814.  
  4815. kAEAlwaysInteract           The server application can interact with the user in
  4816.  
  4817.                                                response to this Apple event—by
  4818.                                                convention, even if no 
  4819.                                                information is needed from the
  4820.                                                user. If this flag is set and 
  4821.                                                the server allows interaction,
  4822.                                                AEInteractWithUser brings 
  4823.                                                the server application to the
  4824.                                                foreground. The Apple 
  4825.                                                Event Manager does not
  4826.                                                distinguish between this flag and
  4827.                                                the kAECanInteract
  4828.                                                flag—distinguishing between them
  4829.                                                is
  4830.                                                the responsibility of the server
  4831.                                                application.
  4832.  
  4833. If the client application doesn’t specify any of the user interface flags, the
  4834. Apple Event Manager sets either the kAENeverInteract or the kAECanInteract flag
  4835. in the keyInteractLevelAttr attribute of the Apple event, depending on the
  4836. location of the server application. If the server application is on a remote
  4837. computer, the Apple Event Manager sets the kAENeverInteract flag as the default.
  4838. If the server application is on the local computer, the Apple Event Manager sets
  4839. the kAECanInteract flag as the default.
  4840.  
  4841. In addition, the client application can set another flag in the sendMode
  4842. parameter to AESend to request that the Apple Event Manager immediately bring
  4843. the server application to the front (instead of posting a notification
  4844. request)—if user interaction is allowed and if the user interface guidelines
  4845. permit. 
  4846.  
  4847. Flag                                        Description
  4848.  
  4849. kAECanSwitchLayer          If both the client and server allow interaction and
  4850. this 
  4851.                                                 flag is set, AEInteractWithUser
  4852.                                                 brings the server directly 
  4853.                                                 to the foreground if adherence
  4854.                                                 to the principle of user 
  4855.                                                 control allows. If the action
  4856.                                                 would be contrary to this 
  4857.                                                 principle, AEInteractWithUser
  4858.                                                 uses the Notification 
  4859.                                                 Manager to request that user
  4860.                                                 bring the server application 
  4861.                                                 to the foreground. If both the
  4862.                                                 client and server allow    
  4863.                                                 interaction and this flag is not
  4864.                                                 set, AEInteractWithUser 
  4865.                                                 always uses the Notification
  4866.                                                 Manager to request that the 
  4867.                                                 user bring the server
  4868.                                                 application to the foreground.
  4869.  
  4870. When a server application calls AEInteractWithUser, the function first checks to
  4871. see if the kAENeverInteract flag in the keyInteractLevelAttr attribute of the
  4872. Apple event is set. (The Apple Event Manager sets this attribute according to
  4873. the flags specified in the sendMode parameter of AESend.) If the
  4874. kAENeverInteract flag is set, AEInteractWithUser immediately returns the
  4875. errAENoUserInteraction result code. If the client specified kAECanInteract or
  4876. kAEAlwaysInteract, AEInteractWithUser checks the server’s preferences for user
  4877. interaction.
  4878.  
  4879. The server sets its user interaction preferences by using the
  4880. AESetInteractionAllowed function. You use this function to tell the Apple Event
  4881. Manager the processes for which your application is willing to interact with the
  4882. user.
  4883.  
  4884. myErr := AESetInteractionAllowed(level);
  4885.  
  4886. The level parameter is of type AEInteractAllowed. 
  4887.  
  4888.    TYPE  AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal, 
  4889.                               kAEInteractWithAll);
  4890.  
  4891. You can specify one of these values for the interaction level.
  4892.  
  4893. Flag                                         Description
  4894.  
  4895. kAEInteractWithSelf          User interaction with your server application in 
  4896.                                                  response to an Apple event may
  4897.                                                  be allowed only when 
  4898.                                                  the client application is your
  4899.                                                  own application—that is, 
  4900.                                                  only when your application is
  4901.                                                  sending the Apple event 
  4902.                                                  to itself.
  4903.  
  4904. kAEInteractWithLocal       User interaction with your server application in 
  4905.                                                  response to an Apple event may
  4906.                                                  be allowed only if the 
  4907.                                                  client application is on the
  4908.                                                  same computer as your 
  4909.                                                  application; this is the
  4910.                                                  default if the 
  4911.                                                  AESetInteractionAllowed
  4912.                                                  function is not used.
  4913.  
  4914. kAEInteractWithAll          User interaction with your server application in
  4915. response
  4916.                                                 to an Apple event may be allowed
  4917.                                                 for any client 
  4918.                                                 application on any computer.
  4919.  
  4920. If the server application does not set the user interaction level,
  4921. AEInteractWithUser uses kAEInteractWithLocal as the value.
  4922.  
  4923. If the application sent itself an Apple event (that is, the application is both
  4924. the client and the server), AEInteractWithUser always allows user interaction.
  4925. If the client application is a process on the local machine, and the server set
  4926. the interaction level to the kAEInteractWithLocal or kAEInteractWithAll flag,
  4927. then AEInteractWithUser allows user interaction. If the client is a process on a
  4928. remote computer on the network, AEInteractWithUser allows user interaction only
  4929. if the server specified the kAEInteractWithAll flag for the interaction level.
  4930. In all other cases, AEInteractWithUser does not allow user interaction.
  4931.  
  4932. When AEInteractWithUser allows user interaction (based on the client and
  4933. server’s preferences), AEInteractWithUser brings the server application to the
  4934. front—either directly or after the user responds to a notification request—and
  4935. then returns a noErr result code. 
  4936.  
  4937. If AEInteractWithUser cannot bring the server application to the front within
  4938. the specified timeout value, AEInteractWithUser returns the errAETimeout result
  4939. code.
  4940.  
  4941. Your application may want to provide the user with a method of setting the
  4942. interaction level. For example, some users may not want to be interrupted while
  4943. background processing of an Apple event occurs, or they may not want to respond
  4944. to dialog boxes when your application is handling Apple events sent from another
  4945. computer.
  4946.  
  4947. Listing 6-14 illustrates the use of the AEInteractWithUser function. You call
  4948. this function before your application displays a dialog box or otherwise
  4949. interacts with the user when processing an Apple event. You specify a timeout
  4950. value, a pointer to a Notification Manager record, and the address of an idle
  4951. function as parameters to AEInteractWithUser.
  4952.  
  4953. ¿ Listing 6-14   Using the AEInteractWithUser function
  4954.  
  4955. myErr := AEInteractWithUser (kAEDefaultTimeOut, NIL, @MyIdleFunction);
  4956. IF myErr <> noErr THEN
  4957.    {the attempt to interact failed, do any error handling}
  4958.    DoError(myErr)
  4959. ELSE
  4960.    {interact with the user by displaying a dialog box }
  4961.    { or by interacting in any other way that is necessary}
  4962.  
  4963. You can set a timeout value, in ticks, in the first parameter to
  4964. AEInteractWithUser. Use the kAEDefaultTimeout constant if you want the Apple
  4965. Event Manager to use a default value for the timeout value. The Apple Event
  4966. Manager uses a timeout value of about one minute if you specify this constant.
  4967. You can also specify the kNoTimeOut constant if your application is willing to
  4968. wait an indefinite amount of time for a response from the user. Usually you
  4969. should provide a timeout value, so that your application can complete processing
  4970. of the Apple event in a reasonable amount of time.
  4971.  
  4972. You can provide a pointer to a Notification Manager record in the second
  4973. parameter, or you can specify NIL to use the default record provided by
  4974. AEInteractWithUser. The AEInteractWithUser function only uses a Notification
  4975. Manager record when user interaction is allowed and the kAECanSwitchLayer flag
  4976. in the keyInteractLevelAttr attribute is not set.
  4977.  
  4978. The last parameter to AEInteractWithUser specifies an idle function provided by
  4979. your application. Your idle function should handle any update events, null
  4980. events, operating-system events, or activate events while your application is
  4981. waiting to be brought to the front. See “Writing an Idle Function” later in this
  4982. chapter for more information.
  4983. _______________________________________________________________________________
  4984.  
  4985. æKY Creating…an…Apple…Event
  4986. æC »Creating an Apple Event                                        The Apple Event Manager
  4987. _______________________________________________________________________________
  4988.  
  4989. You create an Apple event by using the AECreateAppleEvent function. You specify
  4990. the event class and event ID, the target address, the return ID, and the
  4991. transaction ID to the function. The AECreateAppleEvent function creates and
  4992. returns an Apple event with the attributes set as your application requested.
  4993. You should not directly manipulate the contents of the Apple event; rather, use
  4994. Apple Event Manager functions to add additional attributes or parameters to it.
  4995.  
  4996. This example creates a Multiply event using the AECreateAppleEvent function. You
  4997. specify the event class, the event ID, the address of the server application, a
  4998. return ID, a transaction ID, and a buffer to store the returned Apple event as
  4999. parameters to AECreateAppleEvent. 
  5000.  
  5001. myErr := AECreateAppleEvent(kArithmeticClass, kMultEventID,
  5002.                             targetAddress, kAutoGenerateReturnID,
  5003.                             kAnyTransactionID,theAppleEvent);
  5004.  
  5005. The event class here is identified by the kArithmeticClass constant and
  5006. specifies that this event belongs to a specific class of Apple events for
  5007. arithmetic operations. The event ID specifies the particular Apple event within
  5008. the class; in this case, an Apple event to perform multiplication.
  5009.  
  5010. You specify the target of the Apple event in the third parameter to
  5011. AECreateAppleEvent. The target address can identify an application on the local
  5012. computer or another computer on the network. You can specify the address using a
  5013. target ID record or session ID. For processes on the local computer, you can
  5014. also use a process serial number or application signature to specify the
  5015. address. See “Specifying a Target Address” later in this chapter for more
  5016. information. 
  5017.  
  5018. You specify the return ID of the Apple event in the fourth parameter. The return
  5019. ID provides a way to associate this Apple event to the server’s reply. The
  5020. AECreateAppleEvent function assigns the specified return ID value to the
  5021. keyReturnIDAttr attribute of the Apple event. If a server returns an Apple event
  5022. in response to this event, the server should use the same return ID. When you
  5023. receive an Apple event, you can check the keyReturnIDAttr attribute to determine
  5024. whether the event is a response to an outstanding Apple event. You can use the
  5025. kAutoGenerateReturnID constant to request that the Apple Event Manager generate
  5026. a return ID that is unique to this session for the Apple event.
  5027.  
  5028. The fifth parameter specifies the transaction ID attribute of the Apple event. A
  5029. transaction refers to a sequence of Apple events that are sent back and forth
  5030. between the client and server applications, beginning with the client’s initial
  5031. request for a service. All Apple events that are part of one transaction must
  5032. have the same transaction ID.
  5033.  
  5034. You can use a transaction ID to indicate that an Apple event is one of a
  5035. sequence of Apple events related to a single transaction. The kAnyTransactionID
  5036. constant indicates that the Apple event is not part of a transaction.
  5037.  
  5038. The AECreateAppleEvent function creates an Apple event with only the specified
  5039. attributes and no parameters. To add parameters or additional attributes, use
  5040. other Apple Event Manager functions.
  5041. _______________________________________________________________________________
  5042.  
  5043. æKY Adding…Parameters…to…an…Apple…Event
  5044. æC »Adding Parameters to an Apple Event                            The Apple Event Manager
  5045. _______________________________________________________________________________
  5046.  
  5047. You can use the AEPutParamPtr or AEPutParamDesc functions to add parameters to
  5048. an Apple event. When you use either of these functions, the Apple Event Manager
  5049. adds the specified parameter to the Apple event. 
  5050.  
  5051. Use the AEPutParamPtr function when you want to add data specified in a buffer
  5052. as the parameter of an Apple event. You specify the Apple event, the keyword of
  5053. the parameter to add, the descriptor type, a buffer that contains the data, and
  5054. the size of this buffer as parameters to the AEPutParamPtr function. The
  5055. AEPutParamPtr function creates the descriptor record and adds the parameter to
  5056. the Apple event.
  5057.  
  5058. For example, this code adds a parameter to the Multiply event using the
  5059. AEPutParamPtr function.
  5060.  
  5061. CONST  keyOperand1 = 'OPN1';
  5062. VAR
  5063. number1:        Integer;
  5064. theAppleEvent:  AppleEvent;
  5065.  
  5066. number1 := 10;
  5067. myErr := AEPutParamPtr(theAppleEvent, keyOperand1, typeInteger,
  5068.                        @number1, SizeOf(number1));
  5069.  
  5070. In this example, the Apple Event Manager adds the parameter containing the first
  5071. number to the specified Apple event.
  5072.  
  5073. Use the AEPutParamDesc function to add data specified in a descriptor record to
  5074. an Apple event. The descriptor record you specify must have been previously
  5075. created using the AECreateDesc or AEDuplicateDesc function. 
  5076.  
  5077. You specify the descriptor type, a buffer that contains the data, and the size
  5078. of this buffer as parameters to the AECreateDesc function. The AECreateDesc
  5079. function returns the descriptor record that describes the data.
  5080.  
  5081. This example creates a descriptor record for the second parameter of the
  5082. Multiply event:
  5083.  
  5084. VAR
  5085. number2:         Integer;
  5086. multParam2Desc:  AEDesc;
  5087.  
  5088. number2 := 8;
  5089. myErr := AECreateDesc(typeInteger, @number2, SizeOf(number2),
  5090.                       multParam2Desc);
  5091.  
  5092. In this example, the AECreateDesc function creates a descriptor record with the
  5093. typeInteger descriptor type and the data identified in the number2 variable.
  5094.  
  5095. Once you have created a descriptor record, you can use AEPutParamDesc to add the
  5096. data to a parameter of an Apple event. You specify the Apple event to add the
  5097. parameter to, the keyword of the parameter, and the descriptor record of the
  5098. parameter as parameters to the AEPutParamDesc function.
  5099.  
  5100. This example adds a second parameter to the Multiply event using the
  5101. AEPutParamDesc function.
  5102.  
  5103. CONST  keyOperand2 = 'OPN2';
  5104.  
  5105. myErr := AEPutParamDesc(theAppleEvent, keyOperand2, multParam2Desc);
  5106.  
  5107. This example adds the keyOperand2 keyword and the descriptor record created in
  5108. the previous example as the second parameter to the specified Apple event.
  5109.  
  5110. The previous examples showed how to add parameters to the imaginary Multiply
  5111. event. After adding parameters to an Apple event, you can send the Apple event
  5112. using the AESend function. See “Sending an Apple Event” later in this chapter
  5113. for information on using this function.
  5114. _______________________________________________________________________________
  5115.  
  5116. æKY Specifying…a…Target…Address
  5117. æC »Specifying a Target Address                                    The Apple Event Manager
  5118. _______________________________________________________________________________
  5119.  
  5120. When you create an Apple event, you must specify the address of the target. The
  5121. target address identifies the particular application or process that you want to
  5122. send the Apple event to. You can send Apple events to applications on the local
  5123. machine or on remote computers on the network. 
  5124.  
  5125. These are the descriptor types that identify the four methods of addressing an
  5126. Apple event.
  5127.  
  5128.    typeApplSignature                 The application signature of the target
  5129.  
  5130.    typeSessionID                          The session ID of the target
  5131.  
  5132.    typeTargetID                             The target ID record of the target
  5133.  
  5134.    typeProcessSerialNumber     The process serial number of the target
  5135.  
  5136. To address an Apple event to a target on a remote computer on the network, you
  5137. must use either the typeSessionID or typeTargetID descriptor type.
  5138.  
  5139. If your application sends an Apple event to itself, it should address the Apple
  5140. event using a process serial number. Use the kCurrentProcess constant to specify
  5141. the process serial number of your application. This is the fastest way for your
  5142. application to send an Apple event to itself.
  5143.  
  5144. You can use any of the four address types when sending an Apple event to another
  5145. application on the local computer. To allow the user to choose the target of an
  5146. Apple event, use the PPCBrowser function. The PPCBrowser function presents a
  5147. standard user interface for choosing a target application, much as the Standard
  5148. File Package provides a standard user interface for opening and saving files.
  5149.  
  5150. The PPCBrowser function returns information about the application the user chose
  5151. in a targetID record. (Listing 6-16 later in this section shows how to use the
  5152. PPCBrowser function to let the user choose a target.) 
  5153.  
  5154. The Event Manager chapter in this volume describes all four types of addresses.
  5155. Your application can also use another address type, if it also provides a
  5156. coercion handler that coerces the address type into one of the four address
  5157. types that the Apple Event Manager recognizes. See “Writing and Installing
  5158. Coercion Handlers” later in this chapter for more information.
  5159.  
  5160. You specify the address using an address descriptor record (a descriptor record
  5161. of data type AEAddressDesc). You must create a descriptor record of this type
  5162. and then supply the address descriptor record as a parameter to the
  5163. AECreateAppleEvent function.
  5164.  
  5165. You can use the AECreateDesc function to add any of the four target addresses to
  5166. an address descriptor record. Listing 6-15 shows four possible ways to create an
  5167. address, each using a different address type.
  5168.  
  5169. ¿ Listing 6-15   Creating a target address
  5170.  
  5171. PROCEDURE SetTargetAddresses(VAR targetAddress1, targetAddress2,
  5172.                              targetAddress3, targetAddress4:
  5173.                              AEAdressDesc; toTargetID: TargetID; 
  5174.                              thePSN: ProcessSerialNumber; 
  5175.                              theSignature: OSType; 
  5176.                              theSessionID: sessionID);
  5177. VAR
  5178. myErr: OSErr;
  5179.  
  5180. BEGIN
  5181. myErr := AECreateDesc(typeTargetID, @toTargetID, SizeOf(toTargetID),
  5182.                       targetAddress1);
  5183. myErr := AECreateDesc(typeProcessSerialNumber, @thePSN, SizeOf(thePSN),
  5184.                       targetAddress2);
  5185. myErr := AECreateDesc(typeApplSignature, @theSignature, 
  5186.                       SizeOf(theSignature), targetAddress3);
  5187. myErr := AECreateDesc(typeSessionID, @theSessionID, SizeOf(theSessionID),
  5188.                       targetAddress4);
  5189. END;
  5190.  
  5191. You specify the descriptor type for the address, a pointer to the buffer
  5192. containing the address, and the size of the buffer to the AECreateDesc function
  5193. to create an address descriptor record. The AECreateDesc function returns an
  5194. address descriptor record with the specified characteristics.
  5195.  
  5196. After creating an address, you can specify the address in the AECreateAppleEvent
  5197. function. See “Creating an Apple Event” earlier in this chapter for an example
  5198. using the AECreateAppleEvent function. 
  5199.  
  5200. When you specify an address to the AECreateAppleEvent function, the Apple Event
  5201. Manager stores the address in the keyAddressAttr attribute of the Apple event. 
  5202.  
  5203. You can use the PPCBrowser function to create a target ID. Listing 6-16 shows
  5204. how to use the information returned from the PPCBrowser function to create a
  5205. target ID. You can then use AECreateDesc to create the address descriptor record
  5206. for an Apple event.
  5207.  
  5208. ¿ Listing 6-16   Specifying a target address in an Apple event
  5209.  
  5210. FUNCTION GetTargetAddress(myPrompt: Str255; myAppStr: Str255;
  5211.                           VAR myPortInfo: PortInfoRec; 
  5212.                           VAR targetAddress: AEAddressDesc; 
  5213.                           VAR toTargetID: targetID) : OSErr;
  5214.  
  5215. BEGIN      {use PPCBrowser to let user choose the target}
  5216.    myErr := PPCBrowser(myPrompt, myAppStr, FALSE, toTargetID.location, 
  5217.                        myPortInfo, NIL, '');
  5218.    IF myErr <> noErr THEN
  5219.       DoError(myErr);
  5220.    ELSE 
  5221.    BEGIN
  5222.    toTargetID.name := myPortInfo.name;
  5223.             {create the descriptor record for the target address}
  5224.    myErr := AECreateDesc(typeTargetID, @toTargetID, 
  5225.                          SizeOf(toTargetID), targetAddress);
  5226.    IF myErr <> noErr THEN
  5227.       DoError(myErr);
  5228.    END;
  5229.    GetTargetAddress := myErr;
  5230. END;
  5231.  
  5232. See the Program-to-Program Communications Toolbox chapter for more information
  5233. on using the PPCBrowser function.
  5234. _______________________________________________________________________________
  5235.  
  5236. æKY Sending…an…Apple…Event
  5237. æC »Sending an Apple Event                                         The Apple Event Manager
  5238. _______________________________________________________________________________
  5239.  
  5240. To send an Apple event, you first create an Apple event, add parameters and
  5241. attributes to the Apple event, and then use the AESend function to send it. 
  5242.  
  5243. When you send an Apple event, you specify various options to indicate how the
  5244. server should handle the Apple event. You request a user interaction level from
  5245. the server and specify whether the server can directly switch to the foreground
  5246. if user interaction is needed, whether your application is willing to wait for a
  5247. reply Apple event, whether reconnection is allowed, and whether your application
  5248. wants a return receipt for the Apple event.
  5249.  
  5250. You specify these options in the sendMode parameter to AESend. Here are the
  5251. constants that represent these options.
  5252.  
  5253.    CONST  kAENoReply         = $00000001;       {client doesn't want reply}
  5254.           kAEQueueReply      = $00000002;       {client wants to receive }
  5255.                                                 { reply in event queue}
  5256.           kAEWaitReply       = $00000003;       {client wants to receive }
  5257.                                                 { the reply directly and }
  5258.                                                 { will give up the processor}
  5259.           kAENeverInteract   = $00000010;       {server should not }
  5260.                                                 { interact with user}
  5261.           kAECanInteract     = $00000020;       {server can interact }
  5262.                                                 { with user when needed}
  5263.           kAEAlwaysInteract  = $00000030;       {server can always }
  5264.                                                 { interact with user}
  5265.           kAECanSwitchLayer  = $00000040;       {interaction may directly }
  5266.                                                 { bring server to the front}
  5267.           kAEDontReconnect   = $00000080;       {if error, don't reconnect}
  5268.           kAEWantReceipt     = nReturnReceipt;  {client wants a return }
  5269.                                                 { receipt}
  5270.  
  5271. If your application wants a reply Apple event, specify the kAEQueueReply or
  5272. kAEWaitReply flag. If your application wants to receive the reply Apple event in
  5273. its event queue, use kAEQueueReply. If your application wants to receive the
  5274. reply Apple event in the reply parameter of AESend and is willing to give up the
  5275. processor while waiting for the reply, use kAEWaitReply. If your application
  5276. does not want a reply Apple event and does not need to wait for the server to
  5277. handle the Apple event, specify kNoReply. 
  5278.  
  5279. In most cases, your application should use kAEWaitReply or kAENoReply. You
  5280. should not use kAEQueueReply if your application is sending an Apple event to
  5281. itself.
  5282.  
  5283. If your application specifies kAENoReply or kAEQueueReply, the AESend function
  5284. returns immediately after using the Event Manager to send the event. In this
  5285. case, a noErr result code from AESend indicates that the Apple event was
  5286. successfully sent by the Event Manager; it does not mean that the server
  5287. accepted or handled the Apple event. 
  5288.  
  5289. Also, the reply parameter to AESend does not contain valid data on return from
  5290. AESend if your application specifies kAENoReply or kAEQueueReply. The kAENoReply
  5291. flag indicates that the Apple Event Manager will not return the reply Apple
  5292. event to your application. The kAEQueueReply flag indicates that your
  5293. application wants to receive the reply in its event queue rather than through
  5294. the reply parameter of AESend.
  5295.  
  5296. If your application specifies kAEWaitReply, the Apple Event Manager uses the
  5297. Event Manager to send the event. The Apple Event Manager then calls the
  5298. WaitNextEvent function on behalf of your application, causing your application
  5299. to yield the processor. This gives the server application a chance to receive
  5300. and handle the Apple event. Your application continues to yield the processor
  5301. until the server handles the Apple event or the request times out.
  5302.  
  5303. You use one of the three flags—kAENeverInteract, kAECanInteract, or
  5304. kAEAlwaysInteract—to specify whether the server should interact with the user
  5305. when handling the Apple event. Specify kAENeverInteract if the server should not
  5306. interact with the user when handling the Apple event. You might specify this
  5307. constant if you don’t want the user to be interrupted while the server is
  5308. handling the Apple event.
  5309.  
  5310. Use the kAECanInteract flag if the server should interact with the user when
  5311. necessary—for example, if the user needs to supply information to the server.
  5312. Use the kAEAlwaysInteract flag if the server should interact with the user even
  5313. when no information is needed from the user. Note that it is the responsibility
  5314. of the server and client applications to agree on how to interpret the
  5315. kAEAlwaysInteract flag. 
  5316.  
  5317. If the client application does not set any one of the user interaction flags,
  5318. the Apple Event Manager sets a default, depending on the location of the target
  5319. of the Apple event. If the server application is on a remote computer, the Apple
  5320. Event Manager sets the kAENeverInteract flag as the default. If the target of
  5321. the Apple event is on the local computer, the Apple Event Manager sets the
  5322. kAECanInteract flag as the default.
  5323.  
  5324. The server application should call AEInteractWithUser if it needs to interact
  5325. with the user. If user interaction is allowed, the Apple Event Manager brings
  5326. the server to the front if it is not already the foreground process. If the
  5327. kAECanSwitchLayer flag is set and the principle of user control permits, the
  5328. Apple Event Manager directly brings the server application to the front. If the
  5329. action is contrary to the principle of user control, the Apple Event Manager
  5330. posts a notification request to inform the user to bring the server application
  5331. to the front. 
  5332.  
  5333. You should specify the kAECanSwitchLayer flag only when the client and server
  5334. applications reside on the same computer. In general, you should not set this
  5335. flag if it would be confusing or inconvenient to the user for the server
  5336. application to unexpectedly come to the front.
  5337.  
  5338. Specify the kAEDontReconnect flag if the Apple Event Manager should not
  5339. reconnect if it receives a session closed error from the PPC Toolbox. If you
  5340. don’t set this flag, the Apple Event Manager automatically attempts to reconnect
  5341. and reestablish the session.
  5342.  
  5343. Specify the kAEWantReceipt flag if your application wants notification that the
  5344. server did not accept the Apple event. If you specify this flag, the AESend
  5345. function returns the errAEEventNotHandled result code if the server did not
  5346. accept the Apple event.
  5347.  
  5348. Listing 6-17 illustrates how to send a Multiply event (an imaginary Apple event
  5349. for multiplying two long integers). It first creates an Apple event, adds
  5350. parameters containing the numbers to multiply, then sends it, specifying various
  5351. options. It also illustrates how to handle the reply Apple event that contains
  5352. the result.
  5353.  
  5354.    Note: If you want to send Apple events, your application must also handle the
  5355.    required Apple events. See “Handling the Required Apple Events” earlier in
  5356.    this 
  5357.    chapter for information on how to support the required Apple events.
  5358.  
  5359. ¿ Listing 6-17   Sending an Apple event
  5360.  
  5361. FUNCTION MySendMultiplyEvent (serverAddress: AEAddressDesc;
  5362.                               firstOperand: LongInt; secondOperand:
  5363.                               LongInt; replyResultLongInt: LongInt)
  5364.                               : OSErr;
  5365. CONST
  5366. kArithmeticClass    =  'ARTH';      {event class for arithmetic }
  5367.                                     { Apple events}
  5368. kMultipyEventID     =  'MULT';      {event ID for Multiply event}
  5369. keyMultOperand1     =   'OPN1';     {keyword for first parameter }
  5370. keyMultOperand2     =   'OPN2';     {keyword for second parameter }
  5371.  
  5372. VAR
  5373. theAppleEvent:      AppleEvent;
  5374. reply:              AppleEvent;
  5375. returnedType:       DescType;
  5376. actualSize:         LongInt;
  5377. BEGIN
  5378.    myErr := AECreateAppleEvent(kArithmeticClass, kMultiplyEventID,
  5379.                                ServerAddress, kAutoGenerateReturnID,
  5380.                                kAnyTransactionID, theAppleEvent);
  5381.    IF myErr <> noErr THEN
  5382.       DoError(myErr); {failed to create the event}    
  5383.    {add the first operand}
  5384.     myErr := AEPutParamPtr(theAppleEvent, keyMultOperand1, 
  5385.                            typeLongInteger, @firstOperand, 
  5386.                            SizeOf(firstOperand));
  5387.    IF myErr <> noErr THEN
  5388.       DoError(myErr);   {failed to add first parameter - be sure to}
  5389.                         { dispose of the event before leaving routine}
  5390.    {add the second operand with the proper keyword}
  5391.    myErr := AEPutParamPtr(theAppleEvent, keyMultOperand2, 
  5392.                           typeLongInteger, @secondOperand, 
  5393.                           SizeOf(secondOperand));
  5394.    IF myErr <> noErr THEN
  5395.       DoError(myErr);   {Be sure to dispose of the event and first }
  5396.                         { parameter before leaving routine}
  5397.    myErr := AESend(theAppleEvent, reply, kAEWaitReply + kAENeverInteract,
  5398.                    kAENormalPriority, 120, @myIdleFunction, NIL);
  5399.    IF myErr = noErr THEN {Apple event successfully sent}
  5400.    BEGIN       {check if it was successfully handled }
  5401.                { get result code returned by the server’s handler}
  5402.        myErr := AEGetParamPtr(reply, keyErrorNumber, typeLongInteger, 
  5403.                               returnedType, @errNumber, 
  5404.                               Sizeof(errNumber) );
  5405.        IF (myErr = errAEDescNotFound) | (errNumber = noErr) THEN
  5406.           {If keyErrorNumber doesn’t exist or server returned noErr }
  5407.        BEGIN        { then the Apple event was successfully handled. }
  5408.                     { The reply Apple event contains the result in }
  5409.                     { the direct parameter}
  5410.            myErr := AEGetParamPtr(reply, keyDirectObject, typeInteger,
  5411.                                   returnedType, @replyResultLongInt, 
  5412.                                   SizeOf(replyResultLongInt), actualSize);
  5413.            MySendMultiplyEvent := noErr;    
  5414.            Exit(MySendMultiplyEvent);
  5415.        END;
  5416.        ELSE
  5417.        BEGIN      {server returned an error, so get error string}
  5418.           myErr := AEGetParamPtr(reply, keyErrorString, typeChar, 
  5419.                                  returnedType, @errStr, 
  5420.                                  Sizeof(errStr));
  5421.           IF myErr = noErr THEN
  5422.              MyDisplayError(errStr);
  5423.        END;
  5424.      END;
  5425.      ELSE
  5426.      BEGIN
  5427.      {either the Apple event wasn’t successfully dispatched, }
  5428.      { the request timed out, the user canceled, or other error} 
  5429.      END;
  5430.      END;
  5431. MySendMultiplyEvent := myErr;
  5432. END;
  5433.  
  5434. The code in Listing 6-17 first creates an Apple event with kArithmeticClass as
  5435. the event class and kMultipyEventID as the event ID. It also specifies the
  5436. server of the Apple event. See “Specifying a Target Address” in an earlier
  5437. section for information on various ways to specify a target address. See
  5438. “Creating Apple Events” earlier in this chapter for more information on how to
  5439. create an Apple event.
  5440.  
  5441. The Multiply event shown in Listing 6-17 contains two parameters, each of which
  5442. specifies a number to multiply. See “Adding Parameters to an Apple Event”
  5443. earlier in this chapter for examples of how to specify the parameters for the
  5444. AEPutParamPtr function. 
  5445.  
  5446. After adding the parameters to the event, the code uses AESend to send the
  5447. event. The first parameter to AESend specifies the Apple event to send—in this
  5448. example, the Multiply event. The next parameter specifies the reply Apple event.
  5449.  
  5450.  
  5451. This example specifies kAEWaitReply in the third parameter, indicating that the
  5452. client is willing to yield the processor for the specified timeout value (120
  5453. ticks, or 2 seconds). The kAENeverInteract flag indicates that the server should
  5454. not interact with the user when processing the Apple event. The Multiply event
  5455. is sent using normal priority, meaning it is placed at the end of the event
  5456. queue. You can specify the kAEHighPriority flag to place the event in the front
  5457. of the event queue. 
  5458.  
  5459. The next to last parameter specifies the address of an idle function. If you
  5460. specify kAEWaitReply you should provide an idle function. This function should
  5461. process any update events, null events, operating-system events, or activate
  5462. events that occur while your application is waiting for a reply.  See “Writing
  5463. an Idle Function” later in this chapter for sample code that shows an idle
  5464. function. 
  5465.  
  5466. The last parameter to AESend specifies a filter function. You can supply a
  5467. filter function to filter high-level events that your application might receive
  5468. while waiting for a reply Apple event. You can specify NIL for this parameter if
  5469. you do not need to filter high-level events while waiting for a reply. See
  5470. “Writing a Reply Filter Function” later in this chapter for more information. 
  5471.  
  5472. If AESend returns a noErr result code and your application specified
  5473. kAEWaitReply, you should first see whether a result code was returned from the
  5474. handler routine by checking the reply Apple event for the existence of the
  5475. parameter whose keyword is keyErrorNumber. If the keyErrorNumber parameter does
  5476. not exist or contains the noErr result code, you can use AEGetParamPtr to get
  5477. the parameter you’re interested in from the reply Apple event. 
  5478.  
  5479. The code in Listing 6-17 checks the function result of AESend. If AESend returns
  5480. noErr, the code then checks the replyErrorNumber parameter of the reply Apple
  5481. event to determine whether the server successfully handled the Apple event. If
  5482. this parameter exists and indicates an error occurred, then the code gets the
  5483. error string out of the keyErrorString parameter. Otherwise, the server
  5484. performed the request, and the reply Apple event contains the answer to the
  5485. multiplication request.
  5486.  
  5487. When you are done using the Apple event specified in the AESend function and
  5488. finished with the reply Apple event, you must dispose of their descriptor
  5489. records using the AEDisposeDesc function.
  5490. _______________________________________________________________________________
  5491.  
  5492. æKY Dealing…With…Timeouts
  5493. æC »Dealing With Timeouts                                          The Apple Event Manager
  5494. _______________________________________________________________________________
  5495.  
  5496. When your application calls AESend and chooses to wait for the server to handle
  5497. the Apple event, it can also specify the maximum amount of time that it is
  5498. willing to wait for a response. You can specify a timeout value in the timeout
  5499. parameter to AESend. You can either specify a particular length of time, in
  5500. ticks, that your application is willing to wait, or you can specify the
  5501. kNoTimeOut constant or the kAEDefaultTimeout constant. 
  5502.  
  5503. Use the kNoTimeOut constant to indicate that your application is willing to wait
  5504. forever for a response from the server. You should use this value only if your
  5505. application is guaranteed that the server will respond in a reasonable amount of
  5506. time. You should also implement a method of checking if the user wants to
  5507. cancel. The idle function that you specify as a parameter to AESend should check
  5508. the event queue for any instances of Command-period and immediately return TRUE
  5509. as its function result if it finds a request to cancel in the event queue.
  5510.  
  5511. Use the kAEDefaultTimeout constant if you want the Apple Event Manager to use a
  5512. default value for the timeout value. The Apple Event Manager uses a timeout
  5513. value of about one minute if you specify this constant.
  5514.  
  5515. Note that if you set the kAEWaitReply flag and the server doesn’t have a handler
  5516. for the Apple event, AESend returns immediately with the errAEEventNotHandled
  5517. result code.
  5518.  
  5519. If the server doesn’t respond within the length of time specified by the timeout
  5520. value, AESend returns the errAETimeOut result code. This result code does not
  5521. necessarily mean that the server failed to perform the requested action; it only
  5522. means that the server did not complete processing within the specified time. The
  5523. server might still be processing the Apple event, and it might still send a
  5524. reply.
  5525.  
  5526. If the server finishes processing the Apple event sometime after the time
  5527. specified in the timeout parameter has expired, it returns a reply Apple event
  5528. to AEProcessAppleEvent. The Apple Event Manager then returns the reply to the
  5529. client in the reply parameter that the client originally passed to the AESend
  5530. function. 
  5531.  
  5532. This means your application can continue to check the reply Apple event to see
  5533. if the server has responded, even after the time expires. If the server has not
  5534. yet sent the reply when the client attempts to extract data from the reply Apple
  5535. event, the Apple Event Manager functions return the errAEReplyNotArrived result
  5536. code. Once the reply Apple event returns from the server, the client can extract
  5537. the data in the reply.
  5538.  
  5539. Additionally, the server can determine the timeout value specified by the client
  5540. by examining the keyTimeoutAttr attribute in the Apple event. You can use the
  5541. value of this attribute as a rough estimate of how much time your handler has to
  5542. respond. You can assume that your handler has less time to respond than the
  5543. timeout value, because transmitting the Apple event uses some of the available
  5544. time, as does transmitting the reply Apple event back to the client.
  5545.  
  5546. If your handler needs more time than is specified in the keyTimeoutAttr
  5547. attribute, you can reset the timer by using the AEResetTimer function. This
  5548. function resets the timeout value of an Apple event to its starting value.
  5549.  
  5550. _______________________________________________________________________________
  5551.  
  5552. æKY Writing…an…Idle…Function
  5553. æC »Writing an Idle Function                                       The Apple Event Manager
  5554. _______________________________________________________________________________
  5555.  
  5556. This section describes how to write an idle function when using the AESend or
  5557. AEInteractWithUser functions.
  5558.  
  5559. When your application sends an Apple event, you can wait for the server
  5560. application to receive and finish handling the Apple event, or you can continue
  5561. processing. If your application chooses to continue processing, the AESend
  5562. function returns immediately after using the Event Manager to send the event. If
  5563. your application chooses to wait for the server to handle the event, the AESend
  5564. function does not return until either the server application finishes handling
  5565. the Apple event or a specified amount of time expires.
  5566.  
  5567. Your application specifies its preferences by setting flags in the sendMode
  5568. parameter to AESend. Your application can specify kAENoReply if it does not want
  5569. to receive a reply, kAEQueueReply if it wants to receive the reply in its event
  5570. queue, or kAEWaitReply if it wants the reply returned in the reply parameter of
  5571. AESend and is willing to give up the processor while waiting for the reply.
  5572.  
  5573. If your application specifies the kAEWaitReply flag, the AESend function calls
  5574. WaitNextEvent on behalf of your application. This yields the processor to other
  5575. processes, so that the server has an opportunity to receive and process the
  5576. Apple event sent by your application. While your application is waiting for a
  5577. reply, it cannot receive events unless it provides an idle function.
  5578.  
  5579. If your application provides a pointer to an idle function as a parameter to the
  5580. AESend function, AESend calls your idle function whenever an update event, null
  5581. event, operating-system event, or activate event is received for your
  5582. application. Your application can process high-level events that it receives
  5583. while waiting for a reply by providing a reply filter function. See the next
  5584. section, “Writing a Reply Filter Function,” for more information.
  5585.  
  5586. In a similar manner, when your application calls the AEInteractWithUser
  5587. function, your application can also yield the processor. If AEInteractWithUser
  5588. needs to post a notification request to bring your application to the front,
  5589. your application yields the processor until the user brings your application to
  5590. the front. To receive events while waiting for the user to bring your
  5591. application to the front, you must provide an idle function.
  5592.  
  5593. If your application provides a pointer to an idle function as a parameter to the
  5594. AEInteractWithUser function, AEInteractWithUser calls your idle function
  5595. whenever an update event, null event, operating-system event, or activate event
  5596. is received for your application.
  5597.  
  5598. An idle function must use this syntax:
  5599.  
  5600. FUNCTION MyIdleFunction (VAR theEventRecord: EventRecord;
  5601.                          VAR sleepTime: LongInt;
  5602.                          VAR mouseRgn: RgnHandle) : Boolean;
  5603.  
  5604. The parameter theEventRecord is the event record of the event to process. The
  5605. sleepTime parameter and mouseRgn parameters are values that your idle function
  5606. sets the first time it is called; thereafter they contain the values your
  5607. function set. Your idle function should return a Boolean value that indicates
  5608. whether your application wishes to continue waiting. Set the function result to
  5609. TRUE if your application is no longer willing to wait for a reply from the
  5610. server or for the user to bring the application to the front. Set the function
  5611. result to FALSE if your application is still willing to wait.
  5612.  
  5613. The first time your idle function is called, it receives a null event. At this
  5614. time, you should set the values for the sleepTime and mouseRgn parameters. These
  5615. parameters are used in the same way as the sleep and mouseRgn parameters of the
  5616. WaitNextEvent function. Specify in the sleepTime parameter the amount of time
  5617. (in ticks) during which your application agrees to relinquish the processor if
  5618. no events are pending for it.
  5619.  
  5620. In the mouseRgn parameter, you specify a screen region that determines the
  5621. conditions in which your application is to receive notice of mouse-moved events.
  5622. Your idle function receives mouse-moved events only if your application is the
  5623. front application and the mouse strays outside the region you specify.
  5624.  
  5625. Your idle function receives only update events, null events, operating-system
  5626. events, and activate events. When your idle function receives a null event, it
  5627. can use the idle time to update status reports, animate cursors, or perform
  5628. similar tasks. If your idle function receives any of the other events, it should
  5629. handle the event as it normally would if received in its event loop.
  5630.  
  5631. Listing 6-18 shows an example of an idle function that can be used as an idle
  5632. function for AESend or AEInteractWithUser. The idle function processes update
  5633. events, null events, operating-system events, and activate events. The first
  5634. time the function is called it receives a null event. At this time, it sets the
  5635. sleepTime and mouseRgn parameters. The function continues to process events
  5636. until the server finishes handling the Apple event or the user brings the
  5637. application to the front.
  5638.  
  5639. Your application should implement a method of checking to see if the user wants
  5640. to cancel. The MyCancelInQueue function in Listing 6-18 checks the event queue
  5641. for any instances of Command-period and immediately returns TRUE as its function
  5642. result if it finds a request to cancel in the event queue.
  5643.  
  5644. ¿ Listing 6-18   An idle function
  5645.  
  5646. FUNCTION MyIdleFunction (VAR event: EventRecord;
  5647.                          VAR sleeptime: LongInt;
  5648.                          VAR mouseRgn: RgnHandle) : Boolean;
  5649. VAR
  5650.    hiByte: CHAR;
  5651.    myErr:  OSErr;
  5652. BEGIN
  5653.    MyIdleFunction := FALSE;
  5654. {the MyCancelInQueue function checks the event queue for Command-period}
  5655.    IF MyCancelInQueue THEN
  5656.       BEGIN              
  5657.          MyIdleFunction := TRUE;
  5658.          Exit(MyIdleFunction );
  5659.       END;
  5660.    CASE event.what OF
  5661.       updateEvt,
  5662.       activateEvt,  {every idle function should handle these kinds }
  5663.       kOSEvent:    { of events}
  5664.          BEGIN
  5665.             AdjustCursor(event.where, gCursorRgn);  
  5666.             DoEvent(event);
  5667.          END;
  5668.       nullEvent:
  5669.          BEGIN
  5670.             {Set the sleepTime and mouseRgn parameters}
  5671.             mouseRgn := gCursorRgn;
  5672.             sleeptime := 10;  {use the correct value for your app}
  5673.             DoIdle;        {the application’s idle handling}
  5674.          END 
  5675.       END; {CASE}
  5676. END;
  5677. _______________________________________________________________________________
  5678.  
  5679. æKY Writing…a…Reply…Filter…Function
  5680. æC »Writing a Reply Filter Function                                The Apple Event Manager
  5681. _______________________________________________________________________________
  5682.  
  5683. If your application calls AESend and chooses to yield the processor to other
  5684. processes while waiting for a reply, you can provide an idle function to process
  5685. update, null, operating-system, and activate events and, additionally, you can
  5686. provide a reply filter function to process high-level events. The previous
  5687. section describes how an idle function processes events.
  5688.  
  5689. Your reply filter function can process any high-level events that it is willing
  5690. to handle while waiting for a reply Apple event. For example, your application
  5691. can choose to handle Apple events from other processes while waiting. Note,
  5692. however, that your application must maintain any necessary state information.
  5693. Your reply filter function must not accept any Apple events that can change the
  5694. state of your application and make it impossible to return to its previous
  5695. state.
  5696.  
  5697. A reply filter function must use this syntax:
  5698.  
  5699. FUNCTION MyWaitReplyFilter (VAR theEventRecord: EventRecord;
  5700.                             transactionID: LongInt; returnID: LongInt;
  5701.                             sender: AEAddressDesc) : Boolean;
  5702.  
  5703. The parameter theEventRecord is the event record for a high-level event. The
  5704. next three parameters contain valid information only if the event is an Apple
  5705. event. The transactionID parameter is the transaction ID for the Apple event.
  5706. The returnID parameter is the return ID for the Apple event. The sender
  5707. parameter contains the address of the application or process that sent the Apple
  5708. event.
  5709.  
  5710. Your reply filter function should return TRUE as the function result if you want
  5711. to accept the Apple event; otherwise it should return FALSE. If your filter
  5712. function returns TRUE, the Apple Event Manager calls the AEProcessAppleEvent
  5713. function on behalf of your application, and your handler routine is called to
  5714. process the Apple event.
  5715. _______________________________________________________________________________
  5716.  
  5717. æKY Writing…and…Installing…Coercion…Handlers
  5718. æC »Writing and Installing Coercion Handlers                       The Apple Event Manager
  5719. _______________________________________________________________________________
  5720.  
  5721. When your application extracts data from a parameter, it can request that the
  5722. Apple Event Manager return the data using a descriptor type that is different
  5723. from the original descriptor type. For example, when extracting data from the
  5724. direct parameter of the Open Documents event, you can request that the alias
  5725. records be returned as file system specification records. The Apple Event
  5726. Manager can automatically coerce many different types of data from one to
  5727. another. Table 6-1 later in this section shows descriptor types and the sorts of
  5728. coercion that the Apple Event Manager can perform.
  5729.  
  5730. You can also provide your own routines, referred to as coercion handlers, to
  5731. coerce other descriptor types. To install your own coercion handlers, use the
  5732. AEInstallCoercionHandler function. You specify as parameters to this function
  5733.  
  5734.   • the descriptor type of the data coerced by the handler
  5735.  
  5736.   • the descriptor type of the resulting data
  5737.  
  5738.   • the address of the coercion handler for this descriptor type
  5739.  
  5740.   • a reference constant
  5741.  
  5742.   • a Boolean value that indicates whether your coercion handler expects the
  5743.   data to
  5744.      be specified as a descriptor record or as a pointer to the actual data
  5745.  
  5746.   • a Boolean value that indicates whether your coercion handler should be added
  5747.  
  5748.      to your application’s coercion table or the system coercion table
  5749.  
  5750. The system coercion table is a table in the system heap that contains handlers
  5751. that are available to all applications and processes running on the same
  5752. computer. The handlers in your application’s coercion table are available only
  5753. to your application. When the Apple Event Manager is attempting to coerce data,
  5754. it first looks for a coercion handler in your application’s coercion table. If
  5755. it cannot find a handler for the descriptor type, it looks in the system
  5756. coercion table for a handler. If it doesn’t find a handler there either, it
  5757. returns the errAEHandlerNotFound result code.
  5758.  
  5759.    Note: When an application calls a system coercion handler, the A5 register is
  5760.    set 
  5761.    up for the calling application. For this reason, if you provide a system
  5762.    coercion 
  5763.    handler, it should never use A5 global variables or anything that depends on
  5764.    a 
  5765.    particular context; otherwise, the application that calls the system coercion
  5766.  
  5767.    handler may crash.
  5768.  
  5769. You can provide a coercion handler that expects to receive the data in a
  5770. descriptor record or a buffer referred to by a pointer. When you install your
  5771. coercion handler, you specify how your handler wishes to receive the data. It’s
  5772. more efficient for the Apple Event Manager to provide your coercion handler with
  5773. a pointer to the data so, whenever possible, you should write your coercion
  5774. handler so that it can accept a pointer to the data.
  5775.  
  5776. A coercion handler that accepts a pointer to data must be a function with the
  5777. following syntax:
  5778.  
  5779. FUNCTION MyCoercePtr (typeCode: DescType; dataPtr: Ptr;
  5780.                       dataSize: Size; toType: DescType;
  5781.                       handlerRefcon: LongInt;
  5782.                       VAR result: AEDesc) : OSErr; 
  5783.  
  5784. The typeCode parameter is the descriptor type of the original data. The dataPtr
  5785. parameter is a pointer to the data to coerce; the dataSize parameter is the
  5786. length, in bytes, of the data. The toType parameter is the desired descriptor
  5787. type of the resulting data. The handlerRefcon parameter is a reference constant
  5788. that is stored in the coercion table entry for the handler and passed to the
  5789. handler by the Apple Event Manager whenever the handler is called. The result
  5790. parameter is the resulting descriptor record returned by your coercion handler.
  5791.  
  5792. Your coercion handler should coerce the data to the desired descriptor type and
  5793. return the resulting data in the descriptor record specified by the result
  5794. parameter. Your handler should return the noErr result code if your handler
  5795. successfully performs the coercion, and a nonzero result code otherwise.
  5796.  
  5797. A coercion handler that accepts a descriptor record must be a function with the
  5798. following syntax:
  5799.  
  5800. FUNCTION MyCoerceDesc (theAEDesc: AEDesc; toType: DescType;
  5801.                        handlerRefcon: LongInt;
  5802.                        VAR result: AEDesc) : OSErr;
  5803.  
  5804. The parameter theAEDesc is the descriptor record that contains the data to be
  5805. coerced. The toType parameter is the descriptor type of the resulting data. The
  5806. handlerRefcon parameter is a reference constant that is stored in the coercion
  5807. table entry for the handler and passed to the handler by the Apple Event Manager
  5808. whenever the handler is called. The result parameter is the resulting descriptor
  5809. record.
  5810.  
  5811. Your coercion handler should coerce the data in the descriptor record to the
  5812. desired descriptor type and return the resulting data in the descriptor record
  5813. specified by the result parameter. Your handler should return an appropriate
  5814. result code.
  5815.  
  5816. Table 6-1 lists the descriptor types that the Apple Event Manager provides
  5817. coercion for. The first column shows the descriptor type of the data to be
  5818. coerced, and the second column shows the descriptor types that the Apple Event
  5819. Manager can coerce it to.
  5820.  
  5821.    Note: For many Apple Event Manager functions, the Apple Event Manager 
  5822.    attempts to coerce data to the descriptor type you specify even if the result
  5823.    is no 
  5824.    longer meaningful. To ensure that no coercion is performed and that the 
  5825.    descriptor type of the result is of the same descriptor type as the original,
  5826.    specify 
  5827.    typeWildCard for the desired type.
  5828.  
  5829. ¿ Table 6-1   Coercion handling provided by the Apple Event Manager
  5830. _________________________________________________________
  5831. Original                              Desired
  5832. Description
  5833. Descriptor type                  descriptor type
  5834.  
  5835. typeChar                             typeInteger                   Any string
  5836. that is a valid
  5837.                                               typeLongInteger
  5838.                                               representation of a number
  5839.                                               typeSMInt                    can
  5840.                                               be coerced into an
  5841.                                               typeSMFloat
  5842.                                               equivalent numeric value.
  5843.                                              typeShortInteger  
  5844.                                              typeLongFloat     
  5845.                                              typeShortFloat    
  5846.                                              typeExtended 
  5847.                                              typeComp
  5848.                                              typeMagnitude
  5849.  
  5850. typeInteger                         typeChar                       Any numeric
  5851. descriptor type
  5852. typeLongInteger                                                       can be
  5853. coerced into 
  5854. typeSMInt                                                                  the
  5855. equivalent text string.
  5856. typeSMFloat                                             
  5857. typeShortInteger                                        
  5858. typeLongFloat 
  5859. typeShortFloat 
  5860. typeExtended 
  5861. typeComp  
  5862. typeMagnitude
  5863.  
  5864. typeInteger                          typeInteger                 Any numeric
  5865. descriptor type
  5866. typeLongInteger                 typeLongInteger        can be coerced into any
  5867. other
  5868. typeSMInt                            typeSMInt                  numeric
  5869. descriptor type.
  5870.  
  5871. typeSMFloat                        typeSMFloat        
  5872. typeShortInteger                typeShortInteger                    
  5873. typeLongFloat                     typeLongFloat
  5874. typeShortFloat                    typeShortFloat
  5875. typeExtended                       typeExtended
  5876. typeComp                             typeComp 
  5877. typeMagnitude                    typeMagnitude
  5878.  
  5879. typeTrue                               typeBoolean            The result is the
  5880. Boolean value 
  5881.                                                                                
  5882.  
  5883.  
  5884. typeFalse                              typeBoolean             The result is the
  5885. Boolean value 
  5886.                                                                                
  5887.  
  5888.  
  5889. typeEnumerated                typeBoolean              The enumerated value
  5890. 'true' 
  5891.                                                                                
  5892.                                                                                
  5893.                                                                                
  5894.                                                                                
  5895.  
  5896.                                                                                
  5897.                                                                                
  5898.                                                                                
  5899.                                                                                
  5900.  
  5901.                                                                                
  5902.                                                                                
  5903.                                                                                
  5904.                                                                                
  5905.  
  5906.                                                                                
  5907.                                                                                
  5908.  
  5909.  
  5910. typeBoolean                        typeEnumerated      The Boolean value FALSE 
  5911.                                                                                
  5912.                                                                                
  5913.                                                                                
  5914.                                                                                
  5915.  
  5916.                                                                                
  5917.                                                                                
  5918.                                                                                
  5919.                                                                                
  5920.  
  5921.                                                                                
  5922.                                                                                
  5923.                                                                                
  5924.                                                                                
  5925.  
  5926.                                                                                
  5927.                                                                                
  5928.  
  5929.  
  5930. typeShortInteger                typeBoolean               A value of 1 becomes 
  5931.                                                                                
  5932.                                                                                
  5933.                                                                                
  5934.                                                                                
  5935.                                                                                
  5936.  
  5937.                                                                                
  5938.                                                                                
  5939.                                                                                
  5940.                                                                                
  5941.                                                                                
  5942.  
  5943.                                                                                
  5944.                                                                                
  5945.                                                                                
  5946.  
  5947.  
  5948. typeBoolean                       typeShortInteger       A value of FALSE
  5949. becomes 0.
  5950.                                                                                
  5951.                                                                                
  5952.                                                                                
  5953.                                                                                
  5954.                                                                                
  5955.                                                                                
  5956.  
  5957.  
  5958. typeAlias                             typeFSS                       An alias
  5959. record is coerced into a 
  5960.                                                                                
  5961.                                                                                
  5962.                                                                                
  5963.                                                                                
  5964.  
  5965.  
  5966. typeTemporaryID              typeSectionH            A temporary ID is coerced
  5967. into
  5968.                                                                                
  5969.                                                                                
  5970.                                                                                
  5971.                                                                                
  5972.                                                                                
  5973.                                                                                
  5974.  
  5975.  
  5976. typeAppleEvent                typeAppParameters  An Apple event is coerced 
  5977.                                                                                
  5978.                                                                                
  5979.                                                                                
  5980.                                                                                
  5981.                                                                                
  5982.  
  5983.                                                                                
  5984.                                                                                
  5985.                                                                                
  5986.  
  5987.                                                                                
  5988.  
  5989.                                                                                
  5990.                                                                                
  5991.  
  5992.  
  5993. any descriptor type            typeAEList                 A descriptor record is
  5994. coerced 
  5995.                                                                                
  5996.                                                                                
  5997.                                                                                
  5998.                                                                                
  5999.                                                                                
  6000.                                                                                
  6001.  
  6002.                                                                                
  6003.                                                                                
  6004.  
  6005.  
  6006. typeAEList                           type of list item         A descriptor list
  6007. containing a 
  6008.                                                                                
  6009.                                                                                
  6010.                                                                                
  6011.                                                                                
  6012.  
  6013.                                                                                
  6014.                                                                                
  6015.                                                                                
  6016.                                                                                
  6017.                                                                                
  6018.  
  6019. _______________________________________________________________________________
  6020.  
  6021. æKY The…Application…Died…Event
  6022. æC »The Application Died Event                                     The Apple Event Manager
  6023. _______________________________________________________________________________
  6024.  
  6025. If an application launched by your application terminates, either normally or as
  6026. the result of an error, the Process Manager can notify your application by
  6027. sending it an Apple event—the Application Died event. To receive this
  6028. notification, you must set the acceptAppDied flag in your application’s 'SIZE'
  6029. resource. (For a complete description of the 'SIZE' resource, see the Event
  6030. Manager chapter in this volume.) See the Process Management chapter in this
  6031. volume for information on how your application can launch other applications.
  6032.  
  6033. Application Died—inform that an application has terminated
  6034.  
  6035. Event class                        kCoreEventClass
  6036.  
  6037. Event ID                            kAEApplicationDied
  6038.  
  6039. Required parameters      Keyword:                 keyErrorNumber
  6040.                                              Descriptor type:
  6041.                                              typeLongInteger
  6042.                                              Data:                          A
  6043.                                              sign-extended OSErr value. A value
  6044.                                                                                
  6045.                                                                                
  6046.                                                                                
  6047.                                                                                
  6048.                                                                                
  6049.  
  6050.                                                                                
  6051.                                                                                
  6052.                                                                                
  6053.                                                                                
  6054.                                                                                
  6055.                                                                                
  6056.  
  6057.                                                                                
  6058.                                                                                
  6059.                                                                                
  6060.                                                                                
  6061.                                                                                
  6062.                                                                                
  6063.  
  6064.                                               Keyword:
  6065.                                               keyProcessSerialNumber
  6066.                                               Descriptor type:
  6067.                                               typeProcessSerialNumber
  6068.                                               Data:                        The
  6069.                                               process serial number of the  
  6070.                                                                                
  6071.                                                                                
  6072.                                                                                
  6073.  
  6074.  
  6075. Requested action              None. This Apple event is sent only to provide 
  6076.                                               information.
  6077.  
  6078. The Process Manager gets the value of the keyErrorNumber parameter from the
  6079. system global variable DSErrCode. This value can be set either by the
  6080. application before it terminates or by the Operating System (which can occur as
  6081. the result of a hardware exception or other problem).
  6082. _______________________________________________________________________________
  6083.  
  6084. æKY Apple…Event…Manager…Routines…Volume…VI
  6085. æC »Apple Event Manager Routines Volume VI                         The Apple Event Manager
  6086. _______________________________________________________________________________
  6087.  
  6088. This section describes the routines you use to manage Apple event dispatch
  6089. tables, process Apple events, get parameters and attributes from Apple events,
  6090. get data from Apple event data structures, create Apple event data structures,
  6091. add parameters and attributes to Apple events, send Apple events, get
  6092. information about and delete descriptor records, and coerce descriptor types.
  6093. Result codes appear at the end of each function as applicable.
  6094.  
  6095. _______________________________________________________________________________
  6096.  
  6097. æKY Creating…and…Managing…the…Apple…Event…Dispatch…Tables
  6098. æC »Creating and Managing the Apple Event Dispatch Tables          The Apple Event Manager
  6099. _______________________________________________________________________________
  6100.  
  6101. An Apple event dispatch table contains entries that specify the event class and
  6102. event ID that refer to one or more Apple events, the address of the handler
  6103. routine that handles those Apple events, and a reference constant. You use the
  6104. AEInstallEventHandler function to add entries to the Apple event dispatch table.
  6105. Using this function sets up the initial mapping between the handlers in your
  6106. application and the Apple events that they handle.
  6107.  
  6108. If you need to remove any of your Apple event handlers after this mapping is
  6109. established, you can use the AERemoveEventHandler function. To get the address
  6110. of a handler currently in the Apple event dispatch table, use the
  6111. AEGetEventHandler function.
  6112.  
  6113. You use the AEInstallEventHandler function to add an entry to either the
  6114. application or system Apple event dispatch table.
  6115.  
  6116. To create an entry in the Apple event dispatch table, supply the event class,
  6117. event ID, and address of the handler routine that handles Apple events of the
  6118. specified event class and event ID. You also specify a reference constant that
  6119. the Apple Event Manager passes to your handler routine whenever your handler
  6120. processes an Apple event.
  6121.  
  6122. FUNCTION AEInstallEventHandler (theAEEventClass: AEEventClass; 
  6123.                                 theAEEventID: AEEventID; handler: 
  6124.                                 EventHandlerProcPtr; handlerRefcon: 
  6125.                                 LongInt; isSysHandler: Boolean) : OSErr;
  6126.  
  6127. The parameters theAEEventClass and theAEEventID specify the event class and
  6128. event ID of the Apple events to be handled by the handler for this dispatch
  6129. table entry. For these parameters, you must provide one of the following
  6130. combinations:
  6131.  
  6132.   • the event class and event ID of a single Apple event to be dispatched to the
  6133.  
  6134.      handler for this dispatch table entry
  6135.  
  6136.   • the typeWildCard constant for theAEEventClass and an event ID for 
  6137.      theAEEventID, which indicates that Apple events from all event classes
  6138.      whose 
  6139.      event IDs match theAEEventID should be dispatched to the handler for this 
  6140.      dispatch table entry
  6141.  
  6142.   • an event class for theAEEventClass and the typeWildCard constant for 
  6143.      theAEEventID, which indicates that all events from the event class 
  6144.      theAEEventClass should be dispatched to the handler for this dispatch table
  6145.  
  6146.      entry
  6147.  
  6148.   • the typeWildCard constant for both the parameters theAEEventClass and 
  6149.      theAEEventID, which specifies that all Apple events should be dispatched to
  6150.      the 
  6151.      handler for this dispatch table entry
  6152.  
  6153. The handler parameter is a pointer to an Apple event handler for this dispatch
  6154. table entry. Note that a handler in the system dispatch table must reside in the
  6155. system heap; this means that if the value of the isSysHandler parameter is TRUE,
  6156. the handler parameter must point to a location in the system heap.
  6157.  
  6158. The handlerRefcon parameter is a reference constant that is passed by the Apple
  6159. Event Manager to the handler each time the handler is called. If your handler
  6160. doesn’t use a reference constant, use 0 as the value of this parameter. 
  6161.  
  6162. The isSysHandler parameter specifies the Apple event dispatch table to which you
  6163. want to add the handler. If the value of isSysHandler is TRUE, the Apple Event
  6164. Manager adds the handler to the system Apple event dispatch table. Entries in
  6165. the system Apple event dispatch table are available to all applications. If the
  6166. value of isSysHandler is FALSE, the Apple Event Manager adds the handler to your
  6167. application’s Apple event dispatch table. The application Apple event dispatch
  6168. table is searched first; the system Apple event dispatch table is searched only
  6169. if the necessary handler is not found in your application’s Apple event dispatch
  6170. table.
  6171.  
  6172. If there was already an entry in the specified event handler table for the same
  6173. event class and event ID, it is replaced. Therefore, before installing a handler
  6174. for a particular Apple event into the system dispatch table, use the
  6175. AEGetEventHandler function to determine if the table already contains a handler
  6176. for that event. If an entry exists, AEGetEventHandler returns a reference
  6177. constant and a pointer to that event handler. Chain these to your event handler
  6178. by providing pointers to the previous handler and its reference constant in the
  6179. handlerRefcon parameter of AEInstallEventHandler. When your handler is finished,
  6180. use these pointers to call the previous handler.
  6181.  
  6182. If you put your handler code in the system heap or in your own heap, use the
  6183. AERemoveHandler function to remove the handler when your application quits.
  6184.  
  6185.    Note: When an application calls a system Apple event handler, the A5 register
  6186.    is 
  6187.    set up for the calling application. For this reason, if you provide a system
  6188.    Apple 
  6189.    event handler, it should never use A5 global variables or anything that
  6190.    depends 
  6191.    on a particular context; otherwise, the application that calls the system
  6192.    handler 
  6193.    may crash.
  6194.  
  6195.    Result codes
  6196.           noErr                       0         No error
  6197.           paramErr            –50         Parameter error (handler pointer is
  6198.           NIL or odd)
  6199.          memFullErr      –108        Not enough room in heap zone
  6200.  
  6201. The AEGetEventHandler function gets an entry from an Apple event dispatch table.
  6202.  
  6203. FUNCTION AEGetEventHandler (theAEEventClass: AEEventClass; theAEEventID: 
  6204.                             AEEventID; VAR handler: EventHandlerProcPtr; 
  6205.                             VAR handlerRefcon: LongInt; isSysHandler: 
  6206.                             Boolean) : OSErr;
  6207.  
  6208. The parameter theAEEventClass is the value of the event class field of the
  6209. dispatch table entry for the desired Apple event handler, and the parameter
  6210. theAEEventID is the value of the event ID field of the dispatch table entry for
  6211. the desired Apple event handler. You can use the typeWildCard constant for
  6212. either or both of these parameters. (For an explanation of wildcard values, see
  6213. the earlier description of the AEInstallEventHandler function.)
  6214.  
  6215. In the handler parameter, the AEGetEventHandler function returns a pointer to
  6216. the Apple event handler.
  6217.  
  6218. In the handlerRefcon parameter, the AEGetEventHandler function returns the
  6219. reference constant that is passed by the Apple Event Manager to the Apple event
  6220. handler each time the handler is called.
  6221.  
  6222. The isSysHandler parameter specifies the Apple event dispatch table from which
  6223. to get the handler. If isSysHandler is TRUE, the AEGetEventHandler function
  6224. returns the handler from the system dispatch table. If isSysHandler is FALSE,
  6225. AEGetEventHandler returns the handler from your application’s dispatch table.
  6226.  
  6227.    Result codes
  6228.           noErr                                                0        No error
  6229.           errAEHandlerNotFound    –1717        No handler found for an Apple
  6230.           event
  6231.  
  6232. The AERemoveEventHandler function removes an entry from an Apple event dispatch
  6233. table.
  6234.  
  6235. FUNCTION AERemoveEventHandler (theAEEventClass: AEEventClass; 
  6236.                                theAEEventID: AEEventID; handler: 
  6237.                                EventHandlerProcPtr; isSysHandler: 
  6238.                                Boolean) : OSErr;
  6239.  
  6240. The parameter theAEEventClass is the event class for the handler to be removed.
  6241. The parameter theAEEventID is the event ID for the handler to be removed. You
  6242. can use the typeWildCard constant for either or both of these parameters. (For
  6243. an explanation of wildcard values, see the earlier description of the
  6244. AEInstallEventHandler function.)
  6245.  
  6246. The handler parameter is a pointer to the Apple event handler to be removed.
  6247. Although the parameters theAEEventClass and theAEEventID would be sufficient to
  6248. identify the handler to be removed, providing the handler parameter is a
  6249. safeguard that ensures that you’re removing the correct handler.
  6250.  
  6251. The isSysHandler parameter specifies the Apple event dispatch table from which
  6252. to remove the handler. If TRUE, AERemoveEventHandler removes the handler from
  6253. the system dispatch table. If FALSE, AERemoveEventHandler removes the handler
  6254. from your application’s dispatch table.
  6255.  
  6256.    Result codes
  6257.           noErr                                                 0       No error
  6258.           errAEHandlerNotFound     –1717       No handler found for an Apple
  6259.           event
  6260. _______________________________________________________________________________
  6261.  
  6262. æKY Dispatching…Apple…Events
  6263. æC »Dispatching Apple Events                                       The Apple Event Manager
  6264. _______________________________________________________________________________
  6265.  
  6266. After receiving a high-level event (and optionally checking whether it is a type
  6267. of high-level event other than an Apple event that your application might
  6268. support), your application typically calls the AEProcessAppleEvent function to
  6269. determine the type of Apple event received and to call the corresponding handler
  6270. routine.
  6271.  
  6272. The AEProcessAppleEvent function looks first in the application Apple event
  6273. dispatch table and then in the system Apple event dispatch table for an entry
  6274. that matches the event class and event ID of the specified Apple event. If
  6275. AEProcessAppleEvent finds a matching entry, it calls the handler for that Apple
  6276. event.
  6277.  
  6278. FUNCTION AEProcessAppleEvent (theEventRecord: EventRecord) : OSErr;
  6279.  
  6280. The parameter theEventRecord is the event record for the Apple event.
  6281.  
  6282. If the AEProcessAppleEvent function cannot find a handler for an Apple event in
  6283. either the application or system Apple event dispatch table, the Apple Event
  6284. Manager returns the result code errAEEventNotHandled to the server application
  6285. (as the result of the AEProcessAppleEvent function). The Apple Event Manager
  6286. also returns this result code to the client application if the client is waiting
  6287. for a reply.
  6288.  
  6289.    Result codes
  6290.          noErr                                               0       No error
  6291.          memFullErr                            –108       Not enough room in
  6292.          heap zone
  6293.           bufferIsSmall                          –607       Buffer is too small
  6294.           noOutstandingHLE               –608       No outstanding high-level
  6295.           event
  6296.           errAECorruptData               –1702       Data in an Apple event
  6297.           could not be read
  6298.           errAENewerVersion           –1706      Need a newer version of the
  6299.           Apple Event 
  6300.  
  6301.  
  6302.           errAENotAppleEvent         –1707      Event is not an Apple event
  6303.           errAEHandlerNotFound    –1708     A handler for the Apple event wasn’t
  6304.  
  6305.                                                                            found
  6306. _______________________________________________________________________________
  6307.  
  6308. æKY Getting…Parameters…and…Attributes…From…Apple…Events
  6309. æC »Getting Parameters and Attributes From Apple Events            The Apple Event Manager
  6310. _______________________________________________________________________________
  6311.  
  6312. You use the AEGetParamPtr and AEGetParamDesc functions to gain access to the
  6313. parameters of an Apple event. You use the AEGetAttributePtr and
  6314. AEGetAttributeDesc functions to gain access to the attributes of an Apple event.
  6315.  
  6316. The AEGetParamPtr function uses a buffer to return the data contained in a
  6317. specified parameter of an Apple event.
  6318.  
  6319. FUNCTION AEGetParamPtr (theAppleEvent: AppleEvent; theAEKeyword: 
  6320.                         AEKeyword; desiredType: DescType; VAR typeCode: 
  6321.                         DescType; dataPtr: Ptr; maximumSize: Size; 
  6322.                         VAR actualSize: Size) : OSErr;
  6323.  
  6324. The parameter theAppleEvent is the Apple event containing the desired parameter.
  6325.  
  6326. The parameter theAEKeyword is the keyword that specifies the desired parameter.
  6327.  
  6328. The desiredType parameter specifies the descriptor type of the resulting data;
  6329. if the desired parameter is not of this type, the Apple Event Manager attempts
  6330. to coerce it into this type. If the value of desiredType is typeWildCard, no
  6331. coercion is performed, and the descriptor type of the returned data is the same
  6332. as the descriptor type of the parameter. The returned data’s descriptor type is
  6333. returned in the typeCode parameter.
  6334.  
  6335. The dataPtr parameter is a pointer to the buffer for storing the returned data.
  6336.  
  6337. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6338. returned. You must allocate at least this amount of storage for the buffer
  6339. specified by the dataPtr parameter. 
  6340.  
  6341. The AEGetParamPtr function returns in the actualSize parameter the actual
  6342. length, in bytes, of the data for the Apple event parameter. If this value is
  6343. larger than the value of maximumSize, not all of the data for the Apple event
  6344. parameter was returned.
  6345.  
  6346.    Result codes
  6347.           noErr                                             0         No error
  6348.           memFullErr                          –108         Not enough room in
  6349.           heap zone
  6350.           errAECoercionFail             –1700         Data could not be coerced
  6351.           to the requested
  6352.  
  6353.  
  6354.  
  6355.           errAEDescNotFound         –1701         Descriptor record was not
  6356.           found
  6357.           errAEWrongDataType      –1703         Wrong descriptor type
  6358.           errAENotAEDesc                –1704         Not a valid descriptor
  6359.           record
  6360.           errAEReplyNotArrived    –1718         Reply has not yet arrived
  6361.  
  6362. The AEGetParamDesc function returns the descriptor record for an Apple event
  6363. parameter. 
  6364.  
  6365. FUNCTION AEGetParamDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  6366.                          AEKeyword; desiredType: DescType; 
  6367.                          VAR result: AEDesc) : OSErr;
  6368.  
  6369. The parameter theAppleEvent is the Apple event containing the desired parameter.
  6370.  
  6371. The parameter theAEKeyword is the keyword that specifies the desired parameter.
  6372.  
  6373. The desiredType parameter specifies the descriptor type of the resulting
  6374. descriptor record; if the parameter is not of this type, the Apple Event Manager
  6375. attempts to coerce it into this type. If the value of desiredType is
  6376. typeWildCard, no coercion is performed, and the descriptor type of the resulting
  6377. descriptor record is the same as the descriptor type of the Apple event’s
  6378. parameter.
  6379.  
  6380. The AEGetParamDesc function returns in the result parameter the resulting
  6381. descriptor record. This function creates a new descriptor record by copying the
  6382. descriptor record from the parameter. Your application is responsible for using
  6383. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6384. you are finished using it.
  6385.  
  6386. If the function returns a nonzero result code, a descriptor record with the
  6387. typeNull descriptor type is returned. A descriptor record of this type does not
  6388. contain any data.
  6389.  
  6390.    Result codes
  6391.          noErr                                           0       No error
  6392.          memFullErr                        –108       Not enough room in heap
  6393.          zone
  6394.          errAECoercionFail           –1700       Data could not be coerced to
  6395.          the requested 
  6396.  
  6397.                                                                         type
  6398.          errAEDescNotFound        –1701      Descriptor type was not found
  6399.          errAENotAEDesc               –1704      Not a valid descriptor record
  6400.          errAEReplyNotArrived   –1718      Reply has not yet arrived
  6401.  
  6402. The AEGetAttributePtr function uses a buffer to return the data contained in an
  6403. Apple event attribute.
  6404.  
  6405. FUNCTION AEGetAttributePtr (theAppleEvent: AppleEvent; theAEKeyword: 
  6406.                             AEKeyword; desiredType: DescType; 
  6407.                             VAR typeCode: DescType; dataPtr: Ptr; 
  6408.                             maximumSize: Size; VAR actualSize: 
  6409.                             Size) : OSErr;
  6410.  
  6411. The parameter theAppleEvent is the Apple event containing the desired attribute.
  6412.  
  6413. The parameter theAEKeyword is the keyword that specifies the desired attribute.
  6414.  
  6415. The desiredType parameter is the descriptor type of the data to be returned; if
  6416. the desired attribute is not of this type, the Apple Event Manager attempts to
  6417. coerce it into this type. If the value of desiredType is typeWildCard, no
  6418. coercion is performed, and the descriptor type of the returned data is the same
  6419. as the descriptor type of the attribute. The returned data’s descriptor type is
  6420. returned in the typeCode parameter.
  6421.  
  6422. The dataPtr parameter is a pointer to the buffer for storing the data that is
  6423. returned.
  6424.  
  6425. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6426. returned.
  6427.  
  6428. The AEGetAttributePtr function returns in the actualSize parameter the actual
  6429. length, in bytes, of the data for the attribute. If this value is larger than
  6430. the value of maximumSize, not all of the data for the attribute was returned.
  6431.  
  6432.    Result codes
  6433.          noErr                                          0          No error
  6434.          memFullErr                        –108         Not enough room in heap
  6435.          zone
  6436.          errAECoercionFail           –1700         Data could not be coerced to
  6437.          the requested 
  6438.  
  6439.                                                                           type
  6440.          errAEDescNotFound        –1701        Descriptor type was not found
  6441.          errAENotAEDesc              –1704        Not a valid descriptor record
  6442.          errAEReplyNotArrived   –1718       Reply has not yet arrived
  6443.  
  6444. The AEGetAttributeDesc function returns the descriptor record for an Apple event
  6445. attribute.
  6446.  
  6447. FUNCTION AEGetAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  6448.                              AEKeyword; desiredType: DescType; 
  6449.                              VAR result: AEDesc) : OSErr;
  6450.  
  6451. The parameter theAppleEvent is the Apple event containing the desired attribute.
  6452.  
  6453. The parameter theAEKeyword is the keyword that specifies the desired attribute.
  6454.  
  6455. The desiredType parameter is the descriptor type of the descriptor record to be
  6456. returned; if the desired attribute is not of this type, the Apple Event Manager
  6457. attempts to coerce it into this type. If the value of desiredType is
  6458. typeWildCard, no coercion is performed, and the descriptor type of the resulting
  6459. descriptor record is the same as the descriptor type of the attribute.
  6460.  
  6461. The AEGetAttributeDesc function returns in the result parameter the resulting
  6462. descriptor record. This function creates a new descriptor record by copying the
  6463. descriptor record from the parameter. Your application is responsible for using
  6464. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6465. you are finished using it.
  6466.  
  6467. If the function returns a nonzero result code, a descriptor record with the
  6468. typeNull descriptor type is returned. A descriptor record of this type does not
  6469. contain any data.
  6470.  
  6471.    Result codes
  6472.          noErr                                                0       No error
  6473.          memFullErr                             –108       Not enough room in
  6474.          heap zone
  6475.          errAECoercionFail                –1700       Data could not be coerced
  6476.          to the requested
  6477.  
  6478.  
  6479.  
  6480.          errAEDescNotFound            –1701       Descriptor record was not
  6481.          found
  6482.          errAENotAEDesc                  –1704        Not a valid descriptor
  6483.          record
  6484.          errAEReplyNotArrived       –1718        Reply has not yet arrived
  6485. _______________________________________________________________________________
  6486.  
  6487. æKY Counting…the…Items…in…Descriptor…Lists
  6488. æC »Counting the Items in Descriptor Lists                         The Apple Event Manager
  6489. _______________________________________________________________________________
  6490.  
  6491. The AECountItems function counts the number of descriptor records in a
  6492. descriptor list.
  6493.  
  6494. FUNCTION AECountItems (theAEDescList: AEDescList; VAR theCount:
  6495.                        LongInt) : OSErr;
  6496.  
  6497. The parameter theAEDescList is the descriptor list to be counted.
  6498.  
  6499. The AECountItems function returns the number of descriptor records in the list
  6500. in the parameter theCount.
  6501.  
  6502.    Result codes
  6503.           noErr                                   0         No error
  6504.           errAENotAEDesc     –1704         Not a valid descriptor record
  6505. _______________________________________________________________________________
  6506.  
  6507. æKY Getting…Items…From…Descriptor…Lists
  6508. æC »Getting Items From Descriptor Lists                            The Apple Event Manager
  6509. _______________________________________________________________________________
  6510.  
  6511. You can use the AEGetNthPtr and AEGetNthDesc functions to gain access to the
  6512. data in a descriptor list. You can use the AEGetArray function to get data from
  6513. an array contained in a descriptor list.
  6514.  
  6515. The AEGetNthPtr function uses a buffer to return the data for a descriptor
  6516. record in a descriptor list.
  6517.  
  6518. FUNCTION AEGetNthPtr (theAEDescList: AEDescList; index: LongInt; 
  6519.                       desiredType: DescType; VAR theAEKeyword: 
  6520.                       AEKeyword; VAR typeCode: DescType; dataPtr: 
  6521.                       Ptr; maximumSize: Size; VAR actualSize: Size) : 
  6522.                       OSErr;
  6523.  
  6524. The parameter theAEDescList is the descriptor list containing the desired
  6525. descriptor record.
  6526.  
  6527. The index parameter specifies the position of the desired descriptor record in
  6528. the list (for example, 2 specifies the second descriptor record).
  6529.  
  6530. The desiredType parameter is the descriptor type of the resulting data; if the
  6531. descriptor record is not of this type, the Apple Event Manager attempts to
  6532. coerce it into this type. If the value of desiredType is typeWildCard, no
  6533. coercion is performed, and the descriptor type of the resulting data is the same
  6534. as the descriptor type of the original descriptor record.
  6535.  
  6536. If you are getting data from a list of keyword-specified descriptor records, the
  6537. keyword of the specified descriptor record is returned in the parameter
  6538. theAEKeyword; otherwise, the value typeWildCard is returned.
  6539.  
  6540. The returned data’s descriptor type is returned in the typeCode parameter.
  6541.  
  6542. The dataPtr parameter is the pointer to the buffer for storing the data.
  6543.  
  6544. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6545. returned.
  6546.  
  6547. The AEGetNthPtr function returns in the actualSize parameter the actual length,
  6548. in bytes, of the data for the descriptor record. If this value is larger than
  6549. the value of maximumSize, not all of the data for the descriptor record was
  6550. returned.
  6551.  
  6552.    Result codes
  6553.           noErr                                               0       No error
  6554.           memFullErr                            –108       Not enough room in
  6555.           heap zone
  6556.           errAECoercionFail               –1700       Data could not be coerced
  6557.           to the requested
  6558.  
  6559.  
  6560.  
  6561.           errAEDescNotFound           –1701       Descriptor record was not
  6562.           found
  6563.           errAEWrongDataType        –1703        Wrong descriptor type
  6564.           errAENotAEDesc                 –1704        Not a valid descriptor
  6565.           record
  6566.           errAEReplyNotArrived      –1718        Reply has not yet arrived
  6567.  
  6568. The AEGetNthDesc function returns a descriptor record from a descriptor list.
  6569.  
  6570. FUNCTION AEGetNthDesc (theAEDescList: AEDescList; index: LongInt; 
  6571.                        desiredType: DescType; VAR theAEKeyword: 
  6572.                        AEKeyword; VAR result: AEDesc) : OSErr;
  6573.  
  6574. The parameter theAEDescList is the descriptor list from which to get the
  6575. descriptor record.
  6576.  
  6577. The index parameter is the position of the descriptor record to get (for
  6578. example, 2 specifies the second descriptor record in the list).
  6579.  
  6580. The desiredType parameter is the descriptor type of the resulting data; if the
  6581. descriptor record is not of this type, the Apple Event Manager attempts to
  6582. coerce it into this type. If the value of desiredType is typeWildCard, no
  6583. coercion is performed, and the descriptor type of the resulting descriptor
  6584. record is the same as the descriptor type of the original descriptor record.
  6585.  
  6586. If you are getting data from a list of keyword-specified descriptor records, the
  6587. AEGetNthDesc function returns the keyword of the specified descriptor record in
  6588. the parameter theAEKeyword; otherwise, AEGetNthDesc returns the typeWildCard
  6589. constant.
  6590.  
  6591. The AEGetNthDesc function returns in the result parameter the resulting
  6592. descriptor record. This function creates a new descriptor record by copying the
  6593. descriptor record from the parameter. Your application is responsible for using
  6594. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6595. you are finished using it.
  6596.  
  6597. If the function returns a nonzero result code, a descriptor record with the
  6598. typeNull descriptor type is returned. A descriptor record of this type does not
  6599. contain any data.
  6600.  
  6601.    Result codes
  6602.          noErr                                             0     No error
  6603.          memFullErr                          –108     Not enough room in heap
  6604.          zone
  6605.          errAECoercionFail             –1700     Data could not be coerced to
  6606.          the requested 
  6607.  
  6608.                                                                         type
  6609.          errAEDescNotFound         –1701     Descriptor record was not found
  6610.          errAENotAEDesc                –1704     Not a valid descriptor record
  6611.          errAEReplyNotArrived    –1718     Reply has not yet arrived
  6612.  
  6613. The AEGetArray function converts an Apple event array (an array created with the
  6614. AEPutArray function and stored in a descriptor list) into the corresponding
  6615. Pascal or C array.
  6616.  
  6617. FUNCTION AEGetArray (theAEDescList: AEDescList; arrayType: AEArrayType; 
  6618.                      arrayPtr: AEArrayDataPointer; maximumSize: Size; 
  6619.                      VAR itemType: DescType; VAR itemSize: Size; 
  6620.                      VAR itemCount: LongInt) : OSErr;
  6621.  
  6622. The parameter theAEDescList is the descriptor list from which to get the array.
  6623.  
  6624. The arrayType parameter is the Apple event array type to be converted. This is
  6625. specified by one of the following constants: kAEDataArray, kAEPackedArray,
  6626. kAEHandleArray, kAEDescArray, or kAEKeyDescArray.
  6627.  
  6628. The arrayPtr parameter is a pointer to the buffer for storing the array.
  6629.  
  6630. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6631. returned.
  6632.  
  6633. For packed, data, and handle arrays, the itemType parameter returns the
  6634. descriptor type of the array elements that are returned.
  6635.  
  6636. For packed and data arrays, the itemSize parameter returns the size, in bytes,
  6637. of the array elements that are returned.
  6638.  
  6639. The itemCount parameter returns the number of items in the resulting array.
  6640.  
  6641.    Result codes
  6642.           noErr                                              0     No error
  6643.           memFullErr                           –108     Not enough room in heap
  6644.           zone
  6645.           errAEWrongDataType       –1703     Wrong descriptor type
  6646.           errAENotAEDesc                –1704     Not a valid descriptor record
  6647.           errAEReplyNotArrived    –1718     Reply has not yet arrived
  6648. _______________________________________________________________________________
  6649.  
  6650. æKY Getting…Data…From…AE…Records
  6651. æC »Getting Data From AE Records                                   The Apple Event Manager
  6652. _______________________________________________________________________________
  6653.  
  6654. You can use the AEGetKeyPtr and AEGetKeyDesc functions to get data and
  6655. keyword-specified descriptor records out of an AE record or an Apple event.
  6656.  
  6657. The AEGetKeyPtr function uses a buffer to return the data contained in a
  6658. keyword-specified descriptor record. You can use this function to get data out
  6659. of an AE record or an Apple event record.
  6660.  
  6661. FUNCTION AEGetKeyPtr (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  6662.                       desiredType: DescType; VAR typeCode: DescType; 
  6663.                       dataPtr: Ptr; maximumSize: Size; VAR actualSize: 
  6664.                       Size) : OSErr;
  6665.  
  6666. The parameter theAERecord is the AE record from which to get data.
  6667.  
  6668. The parameter theAEKeyword is the keyword that specifies the desired descriptor
  6669. record.
  6670.  
  6671. The desiredType parameter specifies the descriptor type of the resulting data;
  6672. if the desired data is not of this type, the Apple Event Manager attempts to
  6673. coerce it into this type. If the value of desiredType is typeWildCard, no
  6674. coercion is performed, and the descriptor type of resulting data is the same as
  6675. the descriptor type of the original data. The returned data’s descriptor type is
  6676. returned in the typeCode parameter.
  6677.  
  6678. The dataPtr parameter is a pointer to the buffer for storing the data.
  6679.  
  6680. The maximumSize parameter is the maximum length, in bytes, of the data to be
  6681. returned.
  6682.  
  6683. The AEGetKeyPtr function returns in the actualSize parameter the actual length,
  6684. in bytes, of the data for the keyword-specified descriptor record. If this value
  6685. is larger than the value of maximumSize, not all of the data for the
  6686. keyword-specified descriptor record was returned.
  6687.  
  6688.    Result codes
  6689.           noErr                                            0      No error
  6690.           memFullErr                         –108      Not enough room in heap
  6691.           zone
  6692.           errAECoercionFail            –1700      Data could not be coerced to
  6693.           the requested 
  6694.  
  6695.                                                                          type
  6696.           errAEDescNotFound         –1701     Descriptor record was not found
  6697.           errAEWrongDataType      –1703     Wrong descriptor type
  6698.           errAENotAEDesc                –1704     Not a valid descriptor record
  6699.           errAEReplyNotArrived    –1718     Reply has not yet arrived
  6700.  
  6701. The AEGetKeyDesc function returns the descriptor record for a keyword-specified
  6702. descriptor record. You can use this function to get a descriptor record out of
  6703. an AE record or an Apple event.
  6704.  
  6705. FUNCTION AEGetKeyDesc (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  6706.                        desiredType: DescType; VAR result: AEDesc) : 
  6707.                        OSErr;
  6708.  
  6709. The parameter theAERecord is the AE record from which to get the descriptor
  6710. record.
  6711.  
  6712. The parameter theAEKeyword is the keyword that specifies the descriptor record
  6713. to be returned.
  6714.  
  6715. The desiredType parameter specifies the descriptor type of the resulting
  6716. descriptor record; if the original descriptor record is not of this type, the
  6717. Apple Event Manager attempts to coerce it into this type. If the value of
  6718. desiredType is typeWildCard, no coercion is performed, and the descriptor type
  6719. of the resulting descriptor record is the same as the descriptor type of the
  6720. original descriptor record.
  6721.  
  6722. The AEGetKeyDesc function returns in the result parameter the resulting
  6723. descriptor record. This function creates a new descriptor record by copying the
  6724. descriptor record from the AE record. Your application is responsible for using
  6725. the AEDisposeDesc function to dispose of the resulting descriptor record once
  6726. you are finished using it.
  6727.  
  6728. If the function returns a nonzero result code, a descriptor record with the
  6729. typeNull descriptor type is returned. A descriptor record of this type does not
  6730. contain any data.
  6731.  
  6732.    Result codes
  6733.           noErr                                              0     No error
  6734.           memFullErr                           –108     Not enough room in heap
  6735.           zone
  6736.           errAECoercionFail              –1700     Data could not be coerced to
  6737.           the requested 
  6738.  
  6739.                                                                           type
  6740.          errAEDescNotFound           –1701     Descriptor record was not found
  6741.          errAENotAEDesc                 –1704      Not a valid descriptor record
  6742.          errAEReplyNotArrived     –1718      Reply has not yet arrived
  6743. _______________________________________________________________________________
  6744.  
  6745. æKY Requesting…User…Interaction
  6746. æC »Requesting User Interaction                                    The Apple Event Manager
  6747. _______________________________________________________________________________
  6748.  
  6749. Your server application may need to interact with the user while processing an
  6750. Apple event. Your application should use the AEInteractWithUser function before
  6751. actually interacting with the user in response to an Apple event. Your
  6752. application can also specify its user interaction preferences by using the
  6753. AESetInteractionAllowed and AEGetInteractionAllowed functions.
  6754.  
  6755. A server application uses the AESetInteractionAllowed function to specify user
  6756. interaction preferences for responding to Apple events.
  6757.  
  6758. FUNCTION AESetInteractionAllowed (level: AEInteractAllowed) : OSErr;
  6759.  
  6760. The level parameter must be one of three flags: kAEInteractWithSelf,
  6761. kAEInteractWithLocal, or kAEInteractWithAll.
  6762.  
  6763. Specifying the kAEInteractWithSelf flag allows the server application to
  6764. interact with the user in response to an Apple event only when the client
  6765. application and server application are the same—that is, only when the
  6766. application is sending the Apple event to itself.
  6767.  
  6768. Specifying the kAEInteractWithLocal flag allows the server application to
  6769. interact with the user in response to an Apple event only if the client
  6770. application is on the same computer as the server application; this is the
  6771. default if the AESetInteractionAllowed function is not used.
  6772.  
  6773. Specifying the kAEInteractWithAll flag allows the server application to interact
  6774. with the user in response to an Apple event sent from any client application on
  6775. any computer.
  6776.  
  6777.    Result code
  6778.           noErr                                       0           No error
  6779.  
  6780. The AEGetInteractionAllowed function returns a value that indicates the user
  6781. interaction preferences for responding to an Apple event. The value returned is
  6782. the interaction level set by a previous call to AESetInteractionAllowed. The
  6783. default value of kAEInteractWithLocal is returned if your application has not
  6784. used AESetInteractionAllowed to explicitly set the interaction level.
  6785.  
  6786. FUNCTION AEGetInteractionAllowed (VAR level: AEInteractAllowed) : 
  6787.                                   OSErr;
  6788.  
  6789. The level parameter returns one of the following flags: kAEInteractWithSelf,
  6790. kAEInteractWithLocal, or kAEInteractWithAll.
  6791.  
  6792. The kAEInteractWithSelf flag indicates that the server application may interact
  6793. with the user in response to an Apple event only when the client application and
  6794. server application are the same—that is, only when the application is sending
  6795. the Apple event to itself.
  6796.  
  6797. The kAEInteractWithLocal flag indicates that the server application may interact
  6798. with the user in response to an Apple event only if the client application is on
  6799. the same computer as the server application. This is the default if your
  6800. application has not used the AESetInteractionAllowed function to explicitly set
  6801. the interaction level.
  6802.  
  6803. The kAEInteractWithAll flag indicates that the server application may interact
  6804. with the user in response to an Apple event sent from any client application on
  6805. any computer.
  6806.  
  6807.    Result code
  6808.           noErr                                       0           No error
  6809.  
  6810. A server application calls the AEInteractWithUser function before displaying a
  6811. dialog box or alert box or otherwise interacting with the user. If the
  6812. user-interaction preference settings permit the application to come to the
  6813. foreground, this function brings your application to the front, either directly
  6814. or by posting a notification request. 
  6815.  
  6816. FUNCTION AEInteractWithUser (timeOutInTicks: LongInt; nmReqPtr: 
  6817.                              QElemPtr; idleProc: IdleProcPtr) : OSErr;
  6818.  
  6819. The timeOutInTicks parameter is the amount of time (in ticks) that your handler
  6820. is willing to wait for a response from the user.
  6821.  
  6822. The nmReqPtr parameter is a pointer to a Notification Manager record provided by
  6823. your application. You can specify NIL for this parameter to get the default
  6824. notification handling provided by the Apple Event Manager.
  6825.  
  6826. The idleProc parameter is a pointer to your application’s idle function, which
  6827. handles events while waiting for the Apple Event Manager to return control. For
  6828. a description of how to write this function, see “Writing an Idle Function”
  6829. earlier in this chapter.
  6830.  
  6831. The AEInteractWithUser function checks to see if the client application set the
  6832. kAENeverInteract flag for the Apple event and, if so, returns an error. If not,
  6833. then the AEInteractWithUser function checks the server application’s preference
  6834. set by the AESetInteractionAllowed function and compares it against the source
  6835. of the Apple event—that is, whether it came from the same application, another
  6836. application or process on the same computer, or an application or process
  6837. running on another computer. AEInteractWithUser returns the
  6838. errAENoUserInteraction result code if the user-interaction preferences don’t
  6839. allow user interaction. If user interaction is allowed, the Apple Event Manager
  6840. brings your application to the front, either directly or by posting a
  6841. notification request. If AEInteractWithUser returns the noErr result code, then
  6842. your application is in the front and is free to interact with the user.
  6843.  
  6844.    Result code
  6845.           noErr                                               0           No
  6846.           error
  6847.           errAETimeout                       –1712          Apple event timed
  6848.           out
  6849.           errAENoUserInteraction    –1713          No user interaction allowed
  6850. _______________________________________________________________________________
  6851.  
  6852. æKY Requesting…More…Time…to…Respond…to…Apple…Events
  6853. æC »Requesting More Time to Respond to Apple Events                The Apple Event Manager
  6854. _______________________________________________________________________________
  6855.  
  6856. The AEResetTimer function resets the timeout value for an Apple event to its
  6857. starting value. A server application can call this function when it knows it
  6858. cannot fulfill a client application’s request (either by returning a result or
  6859. by sending back a reply Apple event) before the client application is due to
  6860. time out.
  6861.  
  6862. FUNCTION AEResetTimer (reply: AppleEvent) : OSErr;
  6863.  
  6864. The reply parameter is the default reply for an Apple event and is provided by
  6865. the Apple Event Manager. When AEResetTimer is called, the Apple Event Manager
  6866. uses the default reply to send a Reset Timer event to the client application;
  6867. the Apple Event Manager for the client application intercepts this Apple event
  6868. and resets the client application’s timer for the Apple event. (The Reset Timer
  6869. event is never dispatched to a handler, and the client application does not need
  6870. a handler for it.)
  6871.  
  6872.    Result code
  6873.           noErr                                       0           No error
  6874.           errAEReplyNotValid  –1709           AEResetTimer was passed an invalid
  6875.           reply
  6876. _______________________________________________________________________________
  6877.  
  6878. æKY Suspending…and…Resuming…Apple…Event…Handling
  6879. æC »Suspending and Resuming Apple Event Handling                   The Apple Event Manager
  6880. _______________________________________________________________________________
  6881.  
  6882. The AESuspendTheCurrentEvent function suspends the processing of the Apple event
  6883. that is currently being handled.
  6884.  
  6885. FUNCTION AESuspendTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
  6886.  
  6887. The parameter theAppleEvent is the Apple event whose handling is to be
  6888. suspended. Although the Apple Event Manager doesn’t need the parameter
  6889. theAppleEvent to identify the Apple event currently being handled, providing
  6890. this parameter is a safeguard that ensures that you are suspending the correct
  6891. Apple event.
  6892.  
  6893. After a server application makes a successful call to the
  6894. AESuspendTheCurrentEvent function, it is no longer required to return a result
  6895. or a reply for the Apple event that was being handled. It can, however, return a
  6896. result if it later calls the AEResumeTheCurrentEvent function to resume event
  6897. processing.
  6898.  
  6899. The Apple Event Manager does not automatically dispose of Apple events that have
  6900. been suspended or of their default replies. (The Apple Event Manager does,
  6901. however, automatically dispose of a previously suspended Apple event and its
  6902. default reply if the server later resumes processing of the Apple event by
  6903. calling the AEResumeTheCurrentEvent function.) If your server application does
  6904. not resume processing of a suspended Apple event, it is responsible for using
  6905. the AEDisposeDesc function to dispose of both the Apple event and its default
  6906. reply when you are finished with them.
  6907.  
  6908.    Result code
  6909.           noErr                                       0           No error
  6910.  
  6911. The AEResumeTheCurrentEvent function informs the Apple Event Manager that your
  6912. application wants to resume the handling of a previously suspended Apple event
  6913. or that it has completed the handling of the Apple event.
  6914.  
  6915. FUNCTION AEResumeTheCurrentEvent (theAppleEvent, reply: AppleEvent; 
  6916.                                   dispatcher: EventHandlerProcPtr; 
  6917.                                   handlerRefcon: LongInt) : OSErr;
  6918.   
  6919. The parameter theAppleEvent is the Apple event whose processing is to be
  6920. resumed.
  6921.  
  6922. The reply parameter is the default reply that is automatically provided by the
  6923. Apple Event Manager for the Apple event.
  6924.  
  6925. The dispatcher parameter is one of the following:
  6926.  
  6927.   • a pointer to a routine for handling the event
  6928.  
  6929.   • the kAEUseStandardDispatch constant, which causes the Apple event to be 
  6930.      dispatched in the way it was when it was first received
  6931.  
  6932.   • the kAENoDispatch constant, which tells the Apple Event Manager that the 
  6933.      processing of the Apple event is complete and that it does not need to be 
  6934.      dispatched
  6935.  
  6936. If the value of the dispatcher parameter is not kAEUseStandardDispatch, the
  6937. handlerRefcon parameter is a reference constant that is passed to the handler
  6938. when the handler is called. If the value of the dispatcher parameter is
  6939. kAEUseStandardDispatch, the Apple Event Manager ignores the handlerRefcon
  6940. parameter and instead passes the reference constant that is stored in the Apple
  6941. event dispatch table entry for the Apple event. (If you want to pass the same
  6942. reference constant that is stored in the Apple event dispatch table, your
  6943. application can obtain the reference constant by calling the AEGetEventHandler
  6944. function.)
  6945.  
  6946.    Result code
  6947.           noErr                                       0           No error
  6948.  
  6949. The AESetTheCurrentEvent function specifies the Apple event to be handled. There
  6950. is generally no reason for your application to use this function. Instead of
  6951. calling this function, your application should let the Apple Event Manager go
  6952. through the dispatch tables to set the current Apple event.
  6953.  
  6954. FUNCTION AESetTheCurrentEvent (theAppleEvent: AppleEvent) : OSErr;
  6955.  
  6956. The parameter theAppleEvent is the Apple event that is to be handled.
  6957.  
  6958. The AESetTheCurrentEvent function is used only to avoid going through the
  6959. dispatch tables, and is used only in the following way:
  6960.  
  6961.    1.  An application suspends handling of an Apple event by calling the 
  6962.         AESuspendTheCurrentEvent function.
  6963.  
  6964.    2.  The application calls the AESetTheCurrentEvent function to inform the
  6965.    Apple
  6966.         Event Manager that it is handling the Apple event that was previously 
  6967.         suspended. It thereby makes the identity of the Apple event currently
  6968.         being 
  6969.         handled available to routines that call the AEGetTheCurrentEvent
  6970.         function.
  6971.  
  6972.    3.  The application handles the Apple event. When it is finished, it calls
  6973.    the 
  6974.         AEResumeTheCurrentEvent function with the value kAENoDispatch to tell 
  6975.         the Apple Event Manager that the processing of the event is complete and
  6976.         that 
  6977.          the Apple event does not need to be dispatched.
  6978.  
  6979.    Result code
  6980.           noErr                                       0           No error
  6981.  
  6982. The AEGetTheCurrentEvent function returns the Apple event that is currently
  6983. being handled. In many applications, the handling of an Apple event involves one
  6984. or more long chains of calls to routines within the application. The
  6985. AEGetTheCurrentEvent function makes it unnecessary for these calls to include
  6986. the current Apple event as a parameter; the routines can simply call
  6987. AEGetTheCurrentEvent to get the current Apple event when it is needed.
  6988.  
  6989. FUNCTION AEGetTheCurrentEvent (VAR theAppleEvent: AppleEvent) : 
  6990.                                OSErr;
  6991.  
  6992. This function returns the Apple event that is currently being handled in the
  6993. parameter theAppleEvent.
  6994.  
  6995.    Result code
  6996.           noErr                                       0           No error
  6997. _______________________________________________________________________________
  6998.  
  6999. æKY Creating…Apple…Events
  7000. æC »Creating Apple Events                                          The Apple Event Manager
  7001. _______________________________________________________________________________
  7002.  
  7003. The AECreateAppleEvent function creates an Apple event with several important
  7004. attributes but no parameters.
  7005.  
  7006. FUNCTION AECreateAppleEvent (theAEEventClass: AEEventClass; 
  7007.                              theAEEventID: AEEventID; target: 
  7008.                              AEAddressDesc; returnID: Integer; 
  7009.                              transactionID: LongInt; 
  7010.                              VAR result: AppleEvent) : OSErr;
  7011.  
  7012. The parameter theAEEventClass is the event class of the Apple event to be
  7013. created.
  7014.  
  7015. The parameter theAEEventID is the event ID of the Apple event to be created.
  7016.  
  7017. The target parameter is the address of the server application. See “Specifying a
  7018. Target Application” earlier in this chapter for information on how to address an
  7019. Apple event.
  7020.  
  7021. The returnID parameter is the return ID assigned to this Apple event; if the
  7022. kAutoGenerateReturnID constant is used as the value, the Apple Event Manager
  7023. assigns a return ID that is unique to the current session.
  7024.  
  7025. The transactionID parameter is the transaction ID for this Apple event. A
  7026. transaction refers to a sequence of Apple events that are sent back and forth
  7027. between the client and server applications, beginning with the client’s initial
  7028. request for a service. All Apple events that are part of a transaction must have
  7029. the same transaction ID.
  7030.  
  7031. The AECreateAppleEvent function returns in the result parameter the resulting
  7032. Apple event. Your application is responsible for using the AEDisposeDesc
  7033. function to dispose of the resulting Apple event once you are finished using it.
  7034.  
  7035. If the function returns a nonzero result code, a descriptor record with the
  7036. typeNull descriptor type is returned. A descriptor record of this type does not
  7037. contain any data.
  7038.  
  7039.    Result code
  7040.           noErr                                       0           No error
  7041.           memFullErr                    –108           Not enough room in heap
  7042.           zone
  7043. _______________________________________________________________________________
  7044.  
  7045. æKY Creating…and…Duplicating…Descriptor…Records
  7046. æC »Creating and Duplicating Descriptor Records                    The Apple Event Manager
  7047. _______________________________________________________________________________
  7048.  
  7049. The AECreateDesc function takes data and converts it into a descriptor record.
  7050.  
  7051. FUNCTION AECreateDesc (typeCode: DescType; dataPtr: Ptr; dataSize:
  7052.                        Size; VAR result: AEDesc) : OSErr;
  7053.  
  7054. The typeCode parameter is the descriptor type for the resulting descriptor
  7055. record.
  7056.  
  7057. The dataPtr parameter is a pointer to the data for the descriptor record.
  7058.  
  7059. The dataSize parameter is the length, in bytes, of the data for the descriptor
  7060. record.
  7061.  
  7062. The AECreateDesc function returns in the result parameter the resulting
  7063. descriptor record. This function creates a new descriptor record by copying the
  7064. descriptor record from the parameter. Your application is responsible for using
  7065. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7066. you are finished using it.  You normally do this after receiving a result from
  7067. the AESend function.
  7068.  
  7069. If the function returns a nonzero result code, a descriptor record with the
  7070. typeNull descriptor type is returned. A descriptor record of this type does not
  7071. contain any data.
  7072.  
  7073.    Result code
  7074.           noErr                                       0           No error
  7075.           memFullErr                    –108           Not enough room in heap
  7076.           zone
  7077.  
  7078. The AEDuplicateDesc function makes a copy of a descriptor record.
  7079.  
  7080. FUNCTION AEDuplicateDesc (theAEDesc: AEDesc; VAR result: AEDesc) : 
  7081.                           OSErr;
  7082.  
  7083. The parameter theAEDesc is the descriptor record to be copied.
  7084.  
  7085. The AEDuplicateDesc function returns in the result parameter the resulting
  7086. descriptor record. This function creates a new descriptor record by copying the
  7087. descriptor record from the parameter. Your application is responsible for using
  7088. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7089. you are finished using it. You normally do this after receiving a result from
  7090. the AESend function.
  7091.  
  7092. If the function returns a nonzero result code, a descriptor record with the
  7093. typeNull descriptor type is returned. A descriptor record of this type does not
  7094. contain any data.
  7095.  
  7096. It’s common for applications to send Apple events that have one or more
  7097. attributes or parameters in common. For example, if you’re sending a series of
  7098. Apple events to the same application, the address attribute is the same. In
  7099. these cases, the most efficient way to create the necessary Apple events is to
  7100. make a template Apple event that you can then copy—by calling the
  7101. AEDuplicateDesc function—as needed. You then fill in or change the remaining
  7102. parameters and attributes of the copy, send the copy by calling AESend, and then
  7103. dispose of the copy—by calling AEDisposeDesc—after AESend returns a result.
  7104.  
  7105.    Result code
  7106.           noErr                                       0           No error
  7107.           memFullErr                    –108           Not enough room in heap
  7108.           zone
  7109.  
  7110. _______________________________________________________________________________
  7111.  
  7112. æKY Creating…Descriptor…Lists…and…AE…Records
  7113. æC »Creating Descriptor Lists and AE Records                       The Apple Event Manager
  7114. _______________________________________________________________________________
  7115.  
  7116. The AECreateList function creates an empty descriptor list or AE record.
  7117.  
  7118. FUNCTION AECreateList (factoringPtr: Ptr; factoredSize: Size; isRecord:
  7119.                        Boolean; VAR resultList: AEDescList) : OSErr;
  7120.  
  7121. You can compress descriptor lists—thereby saving both space and, in some cases,
  7122. transmission time—by isolating data at the beginning of each descriptor record
  7123. that is the same for all descriptor records in the list. This common data is
  7124. sent only once for all the descriptor records in the list. When an application
  7125. gets descriptor records from a compressed descriptor list, the Apple Event
  7126. Manager automatically decompresses them.
  7127.  
  7128. The factoringPtr parameter is a pointer to the data at the beginning of each
  7129. descriptor that is the same for all descriptor records in the list. (The method
  7130. for compressing descriptor lists is analogous to extracting the common factor
  7131. from two or more numbers.) If there is no common data, or if you decide not to
  7132. isolate the common data, provide NIL as the value of the factoringPtr
  7133. parameter.
  7134.  
  7135. The factoredSize parameter is the size of the common data. If there is no common
  7136. data, or if you decide not to isolate the common data, the value of factoredSize
  7137. must be 0.
  7138.  
  7139. The isRecord parameter is a Boolean value that specifies the kind of list to
  7140. create. If you set its value to TRUE, the Apple Event Manager creates an AE
  7141. record. If you set its value to FALSE, the Apple Event Manager creates a
  7142. descriptor list.
  7143.  
  7144. The AECreateList  function returns in the resultList parameter the resulting
  7145. descriptor list or AE record. This function creates a new descriptor record by
  7146. copying the descriptor record from the parameter. Your application is
  7147. responsible for using the AEDisposeDesc function to dispose of the resulting
  7148. descriptor record once you are finished using it. You normally do this after
  7149. receiving a result from the AESend function.
  7150.  
  7151. If the function returns a nonzero result code, a descriptor record with the
  7152. typeNull descriptor type is returned. A descriptor record of this type does not
  7153. contain any data.
  7154.  
  7155.    Result code
  7156.           noErr                                       0           No error
  7157.           paramErr                            –50           Error in parameter
  7158.           list 
  7159.           memFullErr                    –108           Not enough room in heap
  7160.           zone
  7161. _______________________________________________________________________________
  7162.  
  7163. æKY Adding…Items…to…Descriptor…Lists
  7164. æC »Adding Items to Descriptor Lists                               The Apple Event Manager
  7165. _______________________________________________________________________________
  7166.  
  7167. The AEPutPtr function takes data specified in a buffer and converts it to a
  7168. descriptor record that it adds to a descriptor list.
  7169.  
  7170. FUNCTION AEPutPtr (theAEDescList: AEDescList; index: LongInt; typeCode:
  7171.                    DescType; dataPtr: Ptr; dataSize: Size) : OSErr;
  7172.  
  7173. The parameter theAEDescList is the descriptor list to which to add a descriptor
  7174. record.
  7175.  
  7176. The index parameter is the position in the list for the descriptor record (for
  7177. example, 2 specifies that it must be the second descriptor record). If there was
  7178. already a descriptor record at that position, it is replaced. If the value of
  7179. index is 0, the descriptor record is added at the end of the list.
  7180.  
  7181. The typeCode parameter is the descriptor type for the resulting descriptor
  7182. record.
  7183.  
  7184. The dataPtr parameter is a pointer to the data for the descriptor record.
  7185.  
  7186. The dataSize parameter is the length, in bytes, of the data for the descriptor
  7187. record.
  7188.  
  7189.    Result code
  7190.           noErr                                         0           No error
  7191.           memFullErr                      –108           Not enough room in heap
  7192.           zone
  7193.           errAEWrongDataType  –1703           Wrong descriptor type
  7194.           errAENotAEDesc           –1704           Not a valid descriptor record
  7195.           errAEBadListItem          –1705           Operation involving a list
  7196.           item failed
  7197.           errAEIllegalIndex           –1719           Not a valid list index
  7198.  
  7199. The AEPutDesc function adds a descriptor record to a descriptor list.
  7200.  
  7201. FUNCTION AEPutDesc (theAEDescList: AEDescList; index: LongInt; 
  7202.                     theAEDesc: AEDesc) : OSErr;
  7203.  
  7204. The parameter theAEDescList is the descriptor list to which you are adding a
  7205. descriptor record.
  7206.  
  7207. The index parameter is the position in the list for the descriptor record (for
  7208. example, 2 specifies that it must be the second descriptor record). If there was
  7209. already a descriptor record at that position, it is replaced. If the value of
  7210. index is 0, the descriptor record is added to the end of the list.
  7211.  
  7212. The parameter theAEDesc is the descriptor record to be added to the list.
  7213.  
  7214.    Result code
  7215.           noErr                                         0           No error
  7216.           memFullErr                      –108           Not enough room in heap
  7217.           zone
  7218.           errAEWrongDataType  –1703           Wrong descriptor type
  7219.           errAENotAEDesc           –1704           Not a valid descriptor record
  7220.           errAEBadListItem          –1705           Operation involving a list
  7221.           item failed
  7222.           errAEIllegalIndex           –1719           Not a valid list index
  7223.  
  7224. The AEPutArray function puts the data for an Apple event array into a descriptor
  7225. list.
  7226.  
  7227. FUNCTION AEPutArray (theAEDescList: AEDescList; arrayType: AEArrayType; 
  7228.                      arrayPtr: AEArrayDataPointer; itemType: DescType; 
  7229.                      itemSize: Size; itemCount: LongInt) : OSErr;
  7230.  
  7231. The parameter theAEDescList is the descriptor list into which to put the Apple
  7232. event array. If there are any items already in the descriptor list, they are
  7233. replaced.
  7234.  
  7235. The arrayType parameter is the Apple event array type to be created. This is
  7236. specified by one of the following constants: kAEDataArray, kAEPackedArray,
  7237. kAEHandleArray, kAEDescArray, or kAEKeyDescArray. The kAEDataArray constant
  7238. refers to an array of integers; kAEPackedArray refers to an array of characters;
  7239. kAEHandleArray refers to an array of handles; kAEDescArray refers to an array of
  7240. descriptor records; and kAEKeyDescArray refers to an array of keyword-specified
  7241. descriptor records.
  7242.  
  7243. If you are putting an array into a compressed descriptor list (see the
  7244. description of the AECreateList function for information about compressing
  7245. descriptor lists), the data for each array element must include the data that is
  7246. common to all the descriptor records in the list. The Apple Event Manager
  7247. automatically isolates the data you specified in the call to AECreateList that
  7248. is common to all the elements of the array.
  7249.  
  7250. The arrayPtr parameter is a pointer to the buffer containing the array.
  7251.  
  7252. For packed, data, and handle arrays, the itemType parameter specifies the
  7253. descriptor type of array items to be created.
  7254.  
  7255. For packed and data arrays, the itemSize parameter specifies the size, in bytes,
  7256. of the array items to be created.
  7257.  
  7258. The itemCount parameter is the number of elements in the array.
  7259.  
  7260.    Result code
  7261.           noErr                                         0           No error
  7262.           memFullErr                      –108           Not enough room in heap
  7263.           zone
  7264.           errAEWrongDataType  –1703           Wrong descriptor type
  7265.           errAENotAEDesc           –1704           Not a valid descriptor record
  7266. _______________________________________________________________________________
  7267.  
  7268. æKY Adding…Data…to…AE…Records
  7269. æC »Adding Data to AE Records                                      The Apple Event Manager
  7270. _______________________________________________________________________________
  7271.  
  7272. The AEPutKeyPtr function takes a pointer to data, a descriptor type, and a
  7273. keyword and converts them into a keyword-specified descriptor record that it
  7274. adds to an AE record.
  7275.  
  7276. FUNCTION AEPutKeyPtr (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  7277.                       typeCode: DescType; dataPtr: Ptr; dataSize: 
  7278.                       Size) : OSErr;
  7279.  
  7280. The parameter theAERecord is the AE record to which to add a keyword-specified
  7281. descriptor record.
  7282.  
  7283. The parameter theAEKeyword is the keyword specifying the descriptor record. If
  7284. there was already a descriptor record with this keyword, it is replaced.
  7285.  
  7286. The typeCode parameter is the descriptor type for the keyword-specified
  7287. descriptor record.
  7288.  
  7289. The dataPtr parameter is a pointer to the data for the keyword-specified
  7290. descriptor record.
  7291.  
  7292. The dataSize parameter is the length, in bytes, of the data for the
  7293. keyword-specified descriptor record.
  7294.  
  7295.    Result codes
  7296.           noErr                                             0        No error
  7297.           memFullErr                          –108        Not enough room in
  7298.           heap zone
  7299.           errAEWrongDataType      –1703        Wrong descriptor type
  7300.           errAENotAEDesc               –1704         Not a valid descriptor
  7301.           record
  7302.           errAEBadListItem              –1705         Operation involving a list
  7303.           item failed
  7304.  
  7305. The AEPutKeyDesc function takes a descriptor record and a keyword and converts
  7306. them into a keyword-specified descriptor record that it adds to an AE record.
  7307.  
  7308. FUNCTION AEPutKeyDesc (theAERecord: AERecord; theAEKeyword: AEKeyword; 
  7309.                        theAEDesc: AEDesc) : OSErr;
  7310.  
  7311. The parameter theAERecord is the AE record to which to add the keyword-specified
  7312. descriptor record.
  7313.  
  7314. The parameter theAEKeyword is the keyword specifying the descriptor record. If
  7315. there was already a keyword-specified descriptor record with this keyword, it is
  7316. replaced.
  7317.  
  7318. The parameter theAEDesc is the descriptor record for the keyword-specified
  7319. descriptor record.
  7320.  
  7321.    Result codes
  7322.           noErr                                             0        No error
  7323.           memFullErr                          –108        Not enough room in
  7324.           heap zone
  7325.           errAEWrongDataType      –1703        Wrong descriptor type
  7326.           errAENotAEDesc               –1704         Not a valid descriptor
  7327.           record
  7328.           errAEBadListItem              –1705         Operation involving a list
  7329.           item failed
  7330. _______________________________________________________________________________
  7331.  
  7332. æKY Adding…Parameters…and…Attributes…to…Apple…Events
  7333. æC »Adding Parameters and Attributes to Apple Events               The Apple Event Manager
  7334. _______________________________________________________________________________
  7335.  
  7336. The AEPutParamPtr function takes a pointer to data, a descriptor type, and a
  7337. keyword and converts them into a parameter that it adds to an Apple event.
  7338.  
  7339. FUNCTION AEPutParamPtr (theAppleEvent: AppleEvent; theAEKeyword: 
  7340.                         AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  7341.                         dataSize: Size) : OSErr;
  7342.  
  7343. The parameter theAppleEvent is the Apple event to which you are adding a
  7344. parameter.
  7345.  
  7346. The parameter theAEKeyword is the keyword for the parameter. If there was
  7347. already a parameter with this keyword in the Apple event, it is replaced.
  7348.  
  7349. The typeCode parameter is the descriptor type for the parameter.
  7350.  
  7351. The dataPtr parameter is a pointer to the data for the parameter.
  7352.  
  7353. The dataSize parameter is the length, in bytes, of the data for the parameter.
  7354.  
  7355.    Result codes
  7356.           noErr                                             0        No error
  7357.           memFullErr                          –108        Not enough room in
  7358.           heap zone
  7359.           errAEWrongDataType      –1703        Wrong descriptor type
  7360.           errAENotAEDesc               –1704         Not a valid descriptor
  7361.           record
  7362.           errAEBadListItem              –1705         Operation involving a list
  7363.           item failed
  7364.  
  7365. The AEPutParamDesc function takes a descriptor record, and a keyword and
  7366. converts them into a parameter that it adds to an Apple event.
  7367.  
  7368. FUNCTION AEPutParamDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  7369.                          AEKeyword; theAEDesc: AEDesc) : OSErr;
  7370.  
  7371. The parameter theAppleEvent is the Apple event to which you are adding a
  7372. parameter.
  7373.  
  7374. The parameter theAEKeyword is the keyword for the parameter. If there was
  7375. already a parameter with this keyword in the Apple event, it is replaced.
  7376.  
  7377. The parameter theAEDesc is the descriptor record for the parameter.
  7378.  
  7379.    Result codes
  7380.           noErr                                             0        No error
  7381.           memFullErr                          –108        Not enough room in
  7382.           heap zone
  7383.           errAEWrongDataType      –1703        Wrong descriptor type
  7384.           errAENotAEDesc               –1704         Not a valid descriptor
  7385.           record
  7386.           errAEBadListItem              –1705         Operation involving a list
  7387.           item failed
  7388.  
  7389. The AEPutAttributePtr function takes a pointer to data, a descriptor type, and a
  7390. keyword and converts them into an attribute that it adds to an Apple event.
  7391.  
  7392. FUNCTION AEPutAttributePtr (theAppleEvent: AppleEvent; theAEKeyword: 
  7393.                             AEKeyword; typeCode: DescType; dataPtr: 
  7394.                             Ptr; dataSize: Size) : OSErr;
  7395.  
  7396. The parameter theAppleEvent is the Apple event to which you are adding an
  7397. attribute.
  7398.  
  7399. The parameter theAEKeyword is the keyword of the attribute. If there was already
  7400. an attribute with this keyword in the Apple event, it is replaced.
  7401.  
  7402. The typeCode parameter is the descriptor type for the attribute.
  7403.  
  7404. The dataPtr parameter is a pointer to the buffer containing the data to be
  7405. assigned to the attribute.
  7406.  
  7407. The dataSize parameter is the length, in bytes, of the data to be assigned to
  7408. the attribute.
  7409.  
  7410.    Result codes
  7411.           noErr                                             0        No error
  7412.           memFullErr                          –108        Not enough room in
  7413.           heap zone
  7414.           errAECoercionFail             –1700        Data could not be coerced
  7415.           to the requested 
  7416.  
  7417.                                                                             type
  7418.           errAENotAEDesc               –1704         Not a valid descriptor
  7419.           record
  7420.  
  7421. The AEPutAttributeDesc takes a descriptor record and a keyword and converts them
  7422. into an attribute that it adds to an Apple event.
  7423.  
  7424. FUNCTION AEPutAttributeDesc (theAppleEvent: AppleEvent; theAEKeyword: 
  7425.                              AEKeyword; theAEDesc: AEDesc) : OSErr;
  7426.  
  7427. The parameter theAppleEvent is the Apple event to which you are adding an
  7428. attribute.
  7429.  
  7430. The parameter theAEKeyword is the keyword of the attribute. If there was already
  7431. an attribute with this keyword in the Apple event, it is replaced.
  7432.  
  7433. The parameter theAEDesc is the descriptor record to be assigned to the
  7434. attribute. The descriptor type of the specified descriptor record should match
  7435. the defined descriptor type for that attribute. For example, the
  7436. keyEventSourceAttr attribute has the typeShortInteger descriptor type.
  7437.  
  7438. If the descriptor type required for the attribute is different than the
  7439. descriptor type of the descriptor record, the Apple Event Manager attempts to
  7440. coerce the descriptor record into the required type, with one exception: the
  7441. Apple Event Manager does not attempt to coerce the data for an address
  7442. attribute, thereby allowing applications to use their own address types.
  7443.  
  7444.    Result codes
  7445.           noErr                                             0        No error
  7446.           memFullErr                          –108        Not enough room in
  7447.           heap zone
  7448.           errAECoercionFail             –1700        Data could not be coerced
  7449.           to the requested 
  7450.  
  7451.                                                                             type
  7452.           errAENotAEDesc               –1704         Not a valid descriptor
  7453.           record
  7454. _______________________________________________________________________________
  7455.  
  7456. æKY Sending…Apple…Events
  7457. æC »Sending Apple Events                                           The Apple Event Manager
  7458. _______________________________________________________________________________
  7459.  
  7460. The AESend function sends an Apple event.
  7461.  
  7462. FUNCTION AESend (theAppleEvent: AppleEvent; VAR reply: AppleEvent; 
  7463.                  sendMode: AESendMode; sendPriority: AESendPriority; 
  7464.                  timeOutInTicks: LongInt; idleProc: IdleProcPtr; 
  7465.                  filterProc: EventFilterProcPtr) : OSErr;
  7466.  
  7467. The parameter theAppleEvent specifies the Apple event to be sent.
  7468.  
  7469. The reply parameter specifies the reply Apple event that is returned if you
  7470. specify the kAEWaitReply flag in the sendMode parameter. (If you specify the
  7471. kAEQueueReply flag in the sendMode parameter, you receive the reply Apple event
  7472. in your event queue.) If you specify either the kAEQueueReply flag or the
  7473. kAENoReply flag, the data in the reply Apple event returned by this function is
  7474. not valid. If this function returns a nonzero result, it also returns in the
  7475. reply parameter a descriptor record whose descriptor type is typeNull—that is,
  7476. one that does not contain data. If you specify kAEWaitReply, your application is
  7477. responsible for using the AEDisposeDesc function to dispose of the resulting
  7478. descriptor record.
  7479.  
  7480. The sendMode parameter allows you to specify the following: the reply mode for
  7481. the Apple event (set with one of the constants kAENoReply, kAEQueueReply, or
  7482. kAEWaitReply); the interaction mode (set with one of the constants
  7483. kAENeverInteract, kAECanInteract, or kAEAlwaysInteract); the layer switch mode
  7484. (set with the kAECanSwitchLayer constant); the reconnection mode (set with the
  7485. kAEDontReconnect constant); and the return receipt mode (set with the
  7486. kAEWantReceipt constant). You obtain the value for this parameter by adding the
  7487. appropriate constants. These flags are stored in the interaction level
  7488. attribute, whose keyword is keyInteractLevelAttr. The sendMode flags are
  7489. described in a later part of this section.
  7490.  
  7491. In the sendPriority parameter, you specify flags that determine whether the
  7492. Apple event is put at the back of the event queue (the kAENormalPriority flag)
  7493. or at the front of the queue (the kAEHighPriority flag).
  7494.  
  7495. If the reply mode specified in the sendMode parameter is kAEWaitReply, or if a
  7496. return receipt is requested, the timeOutInTicks parameter specifies the length
  7497. of time (in ticks) that the client application is willing to wait for the reply
  7498. or return receipt from the server application before timing out. Most
  7499. applications should use the kAEDefaultTimeout constant, which tells the Apple
  7500. Event Manager to provide an appropriate timeout duration. If the value of this
  7501. parameter is kNoTimeOut, the Apple event never times out.
  7502.  
  7503. The idleProc parameter specifies a pointer to a function for any tasks (such as
  7504. displaying a wristwatch or spinning beach ball cursor) that the application
  7505. performs while waiting for a reply or a return receipt (see “Writing an Idle
  7506. Function” earlier in this chapter).
  7507.  
  7508. The filterProc parameter specifies a pointer to a routine that accepts certain
  7509. incoming Apple events that are received while the handler waits for a reply or a
  7510. return receipt and filters out the rest (see “Writing a Reply Filter Function”
  7511. earlier in this chapter).
  7512.  
  7513. You can use one of the following flags in the sendMode parameter to specify the
  7514. reply mode for an Apple event. Only one of these flags may be set.
  7515.  
  7516. Flag                                Description
  7517.  
  7518. kAENoReply               Your application does not want a reply Apple event; the
  7519.  
  7520.                                         server processes your Apple event as
  7521.                                         soon as it has the 
  7522.                                         opportunity.
  7523.  
  7524. kAEQueueReply         Your application wants a reply Apple event; the reply
  7525. appears
  7526.                                          in your event queue as soon as the
  7527.                                          server has the 
  7528.                                          opportunity to process and respond to
  7529.                                          your Apple event.
  7530.  
  7531. kAEWaitReply            Your application wants a reply Apple event and is
  7532. willing to 
  7533.                                          give up the processor while waiting for
  7534.                                          the reply; for 
  7535.                                          example, if the server application is
  7536.                                          on the same computer as
  7537.                                          your application, your application
  7538.                                          yields the processor to 
  7539.                                          allow the server to respond to your
  7540.                                          Apple event.
  7541.  
  7542. You can communicate your user-interaction preferences to the server by
  7543. specifying one of these flags in the sendMode parameter of the AESend function.
  7544. Only one of these flags may be set.
  7545.  
  7546. Flag                                Description
  7547.  
  7548. kAENeverInteract      The server application should never interact with the user
  7549. in
  7550.                                          response to this Apple event. If this
  7551.                                          flag is set, 
  7552.                                          AEInteractWithUser does not bring the
  7553.                                          server application to 
  7554.                                          the foreground (this is the default
  7555.                                          when an Apple event is 
  7556.                                          sent to a remote application).
  7557.  
  7558. kAECanInteract           The server application can interact with the user in
  7559. response 
  7560.                                          to this Apple event—by convention, if
  7561.                                          the user needs to 
  7562.                                           supply information to the server. If
  7563.                                           this flag is set and the 
  7564.                                           server allows interaction,
  7565.                                           AEInteractWithUser brings the 
  7566.                                           server application to the foreground
  7567.                                           (this is the default 
  7568.                                           when an Apple event is sent to a local
  7569.                                           application).
  7570.  
  7571. kAEAlwaysInteract     The server application can interact with the user in
  7572. response 
  7573.                                          to this Apple event—by convention, even
  7574.                                          if no information 
  7575.                                          is needed from the user. If this flag
  7576.                                          is set and the server 
  7577.                                          allows interaction, AEInteractWithUser
  7578.                                          brings the server 
  7579.                                          application to the foreground. The
  7580.                                          Apple Event Manager 
  7581.                                          does not distinguish between this flag
  7582.                                          and the 
  7583.                                          kAECanInteract flag—distinguishing
  7584.                                          between them is the
  7585.                                          responsibility of the server
  7586.                                          application.
  7587.  
  7588. The flags in the following list specify the layer switch mode, the reconnection
  7589. mode, and the return receipt mode. Any of these flags may be set.
  7590.  
  7591. Flag                                 Description
  7592.  
  7593. kAECanSwitchLayer     If both the client and server allow interaction and this
  7594. flag 
  7595.                                            is set, AEInteractWithUser brings the
  7596.                                            server directly to the 
  7597.                                            foreground if adherence to the
  7598.                                            principle of user control 
  7599.                                            allows. If the action would be
  7600.                                            contrary to this principle, 
  7601.                                            AEInteractWithUser uses the
  7602.                                            Notification Manager to 
  7603.                                            request that user bring the server
  7604.                                            application to the 
  7605.                                            foreground. If both the client and
  7606.                                            server allow interaction 
  7607.                                            and this flag is not set,
  7608.                                            AEInteractWithUser always uses the 
  7609.                                            Notification Manager to request that
  7610.                                            the user bring the 
  7611.                                            server application to the foreground.
  7612.  
  7613. kAEDontReconnect      Specifies that the Apple Event Manager must not 
  7614.                                            automatically try to reconnect if it
  7615.                                            receives a sessClosedErr 
  7616.                                            result code from the PPC Toolbox.
  7617.  
  7618. kAEWantReceipt          The sender wants to receive a return receipt for this
  7619. Apple 
  7620.                                            event from the Event Manager.
  7621.                                            (Getting a return receipt 
  7622.                                            means only that the receiving
  7623.                                            application accepted the 
  7624.                                            Apple event; the Apple event may or
  7625.                                            may not be handled 
  7626.                                            successfully after it is accepted).
  7627.                                            If the receiving application 
  7628.                                            does not send a return receipt before
  7629.                                            the request times out, 
  7630.                                            AESend returns errAETimeout as its
  7631.                                            function result.
  7632.  
  7633. If the Apple Event Manager cannot find a handler for an Apple event in either
  7634. the application or system Apple event dispatch table, it returns the result code
  7635. errAEEventNotHandled to the server application (as the result of the
  7636. AEProcessAppleEvent function). If the client is waiting for a reply, the Apple
  7637. Event Manager also returns this result code to the client.
  7638.  
  7639. AESend returns noErr as the function result if the Apple event was successfully
  7640. sent by the Event Manager. A noErr result from AESend does not indicate that the
  7641. Apple event was handled successfully; it only indicates that the Apple event was
  7642. successfully sent by the Event Manager. If a result code other than noErr is
  7643. returned by the handler, and if the client is waiting for a reply, it is
  7644. returned in the keyErrorNumber parameter of the reply Apple event.
  7645.  
  7646.    Result codes
  7647.           noErr                                                       0      No
  7648.           error
  7649.           memFullErr                                    –108      Not enough
  7650.           room in heap zone
  7651.           connectionInvalid                         –609      Connection is
  7652.           invalid
  7653.           errAEEventNotHandled            –1708      Event wasn’t handled by an
  7654.           Apple 
  7655.                                                                                
  7656.                                                                                
  7657.  
  7658.           errAEUnknownSendMode       –1710      Invalid sending mode was passed
  7659.           errAEWaitCanceled                     –1711      User canceled out of
  7660.           wait loop for 
  7661.                                                                                
  7662.                                                                                
  7663.                                                                                
  7664.  
  7665.           errAETimeout                              –1712      Apple event timed
  7666.           out
  7667.           errAEUnknownAddressType   –1716      Unknown Apple event address type
  7668. _______________________________________________________________________________
  7669.  
  7670. æKY Getting…the…Sizes…and…Descriptor…Types…of…Descriptor…Records
  7671. æC »Getting the Sizes and Descriptor Types of Descriptor Records   The Apple Event Manager
  7672. _______________________________________________________________________________
  7673.  
  7674. The AESizeOfNthItem function returns the size and descriptor type of a
  7675. descriptor record in a descriptor list.
  7676.  
  7677. FUNCTION AESizeOfNthItem (theAEDescList: AEDescList; index: LongInt; 
  7678.                           VAR typeCode: DescType; VAR dataSize: Size) 
  7679.                           : OSErr;
  7680.  
  7681. The parameter theAEDescList is the descriptor list containing the descriptor
  7682. record.
  7683.  
  7684. The index parameter is the position of the descriptor record in the list (for
  7685. example, 2 specifies the second descriptor record).
  7686.  
  7687. The AESizeOfNthItem function returns the descriptor type of the descriptor
  7688. record in the typeCode parameter .
  7689.  
  7690. This function returns the length, in bytes, of the data contained in the
  7691. descriptor record in the dataSize parameter.
  7692.  
  7693.    Result codes
  7694.           noErr                                              0      No error
  7695.           errAEDescNotFound          –1701      Descriptor record was not found
  7696.           errAEReplyNotArrived    –1718       Reply has not yet arrived
  7697.  
  7698. The AESizeOfKeyDesc function returns the size and descriptor type of a
  7699. keyword-specified descriptor record in an AE record.
  7700.  
  7701. FUNCTION AESizeOfKeyDesc (theAERecord: AERecord; theAEKeyword: 
  7702.                           AEKeyword; VAR typeCode: DescType; 
  7703.                           VAR dataSize: Size) : OSErr;
  7704.  
  7705. The parameter theAERecord is the AE record containing the desired
  7706. keyword-specified descriptor record.
  7707.  
  7708. The parameter theAEKeyword is the keyword that specifies the desired descriptor
  7709. record.
  7710.  
  7711. This function returns the descriptor type of the desired keyword-specified
  7712. descriptor record in the typeCode parameter.
  7713.  
  7714. This function returns the length, in bytes, of the data contained in the
  7715. keyword-specified descriptor record in the dataSize parameter.
  7716.  
  7717.    Result codes
  7718.           noErr                                               0      No error
  7719.           errAEDescNotFound           –1701      Descriptor record was not found
  7720.           errAENotAEDesc                 –1704      Not a valid descriptor
  7721.           record
  7722.           errAEReplyNotArrived     –1718       Reply has not yet arrived
  7723.  
  7724. The AESizeOfParam function returns the size and descriptor type of an Apple
  7725. event parameter.
  7726.  
  7727. FUNCTION AESizeOfParam (theAppleEvent: AppleEvent; theAEKeyword: 
  7728.                         AEKeyword; VAR typeCode: DescType; 
  7729.                         VAR dataSize: Size) : OSErr;
  7730.  
  7731. The parameter theAppleEvent is the Apple event containing the parameter.
  7732.  
  7733. The parameter theAEKeyword is the keyword that specifies the desired parameter.
  7734.  
  7735. The function returns the descriptor type of the parameter in the typeCode
  7736. parameter.
  7737.  
  7738. The function returns the length, in bytes, of the data contained in the desired
  7739. parameter in the dataSize parameter.
  7740.  
  7741.    Result codes
  7742.           noErr                                               0      No error
  7743.           errAEDescNotFound           –1701      Descriptor record was not found
  7744.           errAENotAEDesc                 –1704      Not a valid descriptor
  7745.           record
  7746.           errAEReplyNotArrived     –1718       Reply has not yet arrived
  7747.  
  7748. The AESizeOfAttribute function returns the size and descriptor type of an Apple
  7749. event attribute.
  7750.  
  7751. FUNCTION AESizeOfAttribute (theAppleEvent: AppleEvent; theAEKeyword: 
  7752.                             AEKeyword; VAR typeCode: DescType; 
  7753.                             VAR dataSize: Size) : OSErr;
  7754.  
  7755. The parameter theAppleEvent is the Apple event containing the attribute.
  7756.  
  7757. The parameter theAEKeyword is the keyword that specifies the attribute.
  7758.  
  7759. The function returns the descriptor type of the attribute in the typeCode
  7760. parameter.
  7761.  
  7762. The function returns the length, in bytes, of the data contained in the
  7763. attribute in the dataSize parameter.
  7764.  
  7765.    Result codes
  7766.           noErr                                               0      No error
  7767.           errAEDescNotFound           –1701      Descriptor record was not found
  7768.           errAENotAEDesc                 –1704      Not a valid descriptor
  7769.           record
  7770.           errAEReplyNotArrived     –1718       Reply has not yet arrived
  7771. _______________________________________________________________________________
  7772.  
  7773. æKY Deleting…Descriptor…Records
  7774. æC »Deleting Descriptor Records                                    The Apple Event Manager
  7775. _______________________________________________________________________________
  7776.  
  7777. The AEDeleteItem function deletes a descriptor record from a descriptor list.
  7778.  
  7779. FUNCTION AEDeleteItem (theAEDescList: AEDescList; index: LongInt) : 
  7780.                        OSErr;
  7781.  
  7782. The parameter theAEDescList is the descriptor list containing the descriptor
  7783. record to be deleted.
  7784.  
  7785. The index parameter is the position of the descriptor record to delete (for
  7786. example, 2 specifies the second item).
  7787.  
  7788.    Result codes
  7789.           noErr                                               0      No error
  7790.           errAEDescNotFound           –1701      Descriptor record was not found
  7791.           errAENotAEDesc                 –1704      Not a valid descriptor
  7792.           record
  7793.           errAEBadListItem                –1705      Operation involving a list
  7794.           item failed
  7795.  
  7796. The AEDeleteKeyDesc function deletes a keyword-specified descriptor record from
  7797. an AE record.
  7798.  
  7799. FUNCTION AEDeleteKeyDesc (theAERecord: AERecord; theAEKeyword: 
  7800.                           AEKeyword) : OSErr;
  7801.  
  7802. The parameter theAERecord is the AE record containing the keyword-specified
  7803. descriptor record to be deleted.
  7804.  
  7805. The parameter theAEKeyword is the keyword that specifies the descriptor record
  7806. to be deleted.
  7807.  
  7808.    Result codes
  7809.           noErr                                               0      No error
  7810.           errAEDescNotFound           –1701      Descriptor record was not found
  7811.           errAENotAEDesc                 –1704      Not a valid descriptor
  7812.           record
  7813.           errAEBadListItem                –1705      Operation involving a list
  7814.           item failed
  7815.  
  7816. The AEDeleteParam function deletes an Apple event parameter.
  7817.  
  7818. FUNCTION AEDeleteParam (theAppleEvent: AppleEvent; theAEKeyword: 
  7819.                         AEKeyword) : OSErr;
  7820.  
  7821. The parameter theAppleEvent is the Apple event containing the parameter to be
  7822. deleted.
  7823.  
  7824. The parameter theAEKeyword is the keyword that specifies the parameter to be
  7825. deleted.
  7826.  
  7827.    Result codes
  7828.           noErr                                               0      No error
  7829.           errAEDescNotFound           –1701      Descriptor record was not found
  7830.           errAENotAEDesc                 –1704      Not a valid descriptor
  7831.           record
  7832.           errAEBadListItem                –1705      Operation involving a list
  7833.           item failed
  7834. _______________________________________________________________________________
  7835.  
  7836. æKY Deallocating…Memory…for…Descriptor…Records
  7837. æC »Deallocating Memory for Descriptor Records                     The Apple Event Manager
  7838. _______________________________________________________________________________
  7839.  
  7840. The AEDisposeDesc function deallocates the memory used by a descriptor record.
  7841. Because all Apple event structures (except for keyword-specified descriptor
  7842. records) are descriptor records, you can use AEDisposeDesc for any of them.
  7843.  
  7844. FUNCTION AEDisposeDesc (VAR theAEDesc: AEDesc) : OSErr;
  7845.  
  7846. The parameter theAEDesc is the descriptor record to deallocate.
  7847.  
  7848.    Result codes
  7849.           noErr                                               0      No error
  7850. _______________________________________________________________________________
  7851.  
  7852. æKY Coercing…Descriptor…Types
  7853. æC »Coercing Descriptor Types                                      The Apple Event Manager
  7854. _______________________________________________________________________________
  7855.  
  7856. <Intro section  here? Why use these, and so on>
  7857. The AECoercePtr function takes a pointer to data and a desired descriptor type
  7858. and attempts to coerce the data into the desired descriptor type. If successful,
  7859. it creates a descriptor record containing the newly coerced data.
  7860.  
  7861. FUNCTION AECoercePtr (typeCode: DescType; dataPtr: Ptr; dataSize: Size;
  7862.                       toType: DescType; VAR result: AEDesc) : OSErr;
  7863.  
  7864. The typeCode parameter is the descriptor type of the source data.
  7865.  
  7866. The dataPtr parameter is a pointer to the data to be coerced.
  7867.  
  7868. The dataSize parameter is the length, in bytes, of the data to be coerced.
  7869.  
  7870. The toType parameter is the desired descriptor type of the resulting descriptor
  7871. record.
  7872.  
  7873. The AECoercePtr function function returns in the result parameter the resulting
  7874. descriptor record. This function creates a new descriptor record by copying the
  7875. descriptor record from the parameter. Your application is responsible for using
  7876. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7877. you are finished using it.
  7878.  
  7879. If the function returns a nonzero result code, a descriptor record with the
  7880. typeNull descriptor type is returned. A descriptor record of this type does not
  7881. contain any data.
  7882.  
  7883.    Note: To avoid infinite recursion, AECoercePtr must never be called by an 
  7884.    application-supplied coercion routine.
  7885.  
  7886.    Result codes
  7887.           noErr                                      0      No error
  7888.           memFullErr                   –108      Not enough room in heap zone
  7889.           errAECoercionFail      –1700      Data could not be coerced to the
  7890.           requested 
  7891.  
  7892. The AECoerceDesc function coerces the data in a descriptor record to another
  7893. descriptor type.
  7894.  
  7895. FUNCTION AECoerceDesc (theAEDesc: AEDesc; toType: DescType; VAR result:
  7896.                        AEDesc) : OSErr;
  7897.  
  7898. The parameter theAEDesc is the descriptor record whose data is to be coerced.
  7899.  
  7900. The toType parameter is the desired descriptor type of the resulting descriptor
  7901. record.
  7902.  
  7903. The AECoerceDesc function returns in the result parameter the resulting
  7904. descriptor record. This function creates a new descriptor record by copying the
  7905. descriptor record from the parameter. Your application is responsible for using
  7906. the AEDisposeDesc function to dispose of the resulting descriptor record once
  7907. you are finished using it.
  7908.  
  7909. If the function returns a nonzero result code, a descriptor record with the
  7910. typeNull descriptor type is returned. A descriptor record of this type does not
  7911. contain any data.
  7912.  
  7913.    Note: To avoid infinite recursion, AECoerceDesc must never be called by an
  7914.    application-supplied coercion routine.
  7915.  
  7916.    Result codes
  7917.           noErr                                      0      No error
  7918.           memFullErr                   –108      Not enough room in heap zone
  7919.           errAECoercionFail      –1700      Data could not be coerced to the
  7920.           requested 
  7921.                                                                    descriptor
  7922.                                                                    type
  7923. _______________________________________________________________________________
  7924.  
  7925. æKY Creating…and…Managing…the…Coercion…Handler…Tables
  7926. æC »Creating and Managing the Coercion Handler Tables              The Apple Event Manager
  7927. _______________________________________________________________________________
  7928.  
  7929. The AEInstallCoercionHandler function installs a coercion handler routine in
  7930. either the application or system coercion table.
  7931.  
  7932. FUNCTION AEInstallCoercionHandler (fromType: DescType; toType: DescType; 
  7933.                                    handler: ProcPtr; handlerRefcon: 
  7934.                                    LongInt; fromTypeIsDesc: Boolean; 
  7935.                                    isSysHandler: Boolean) : OSErr;
  7936.  
  7937. The fromType parameter is the descriptor type of the data coerced by the
  7938. handler, and the toType parameter is the descriptor type of the resulting data.
  7939. If there was already an entry in the specified coercion handler table for the
  7940. same source descriptor type and result descriptor type, it is replaced.
  7941.  
  7942. Therefore, before installing a handler for a particular descriptor type into the
  7943. system coercion table, use the AEGetCoercionHandler function to determine if the
  7944. table already contains a handler for that descriptor type. If an entry exists,
  7945. AEGetCoercionHandler returns a reference constant and a pointer to that handler.
  7946. Chain these to your coercion handler by providing pointers to the previous
  7947. handler and its reference constant in the handlerRefcon parameter of
  7948. AEInstallCoercionHandler. When your handler is finished, use these pointers to
  7949. call the previous handler.
  7950.  
  7951. The handler parameter is a pointer to the coercion handler routine. Note that a
  7952. handler in the system coercion table must reside in the system heap; this means
  7953. that if the value of the isSysHandler parameter is TRUE, the handler parameter
  7954. must point to a location in the system heap.
  7955.  
  7956. The handlerRefcon parameter is a reference constant that is passed by the Apple
  7957. Event Manager to the handler each time the handler is called. If your handler
  7958. doesn’t expect a reference constant, use 0 as the value of this parameter.
  7959.  
  7960. The fromTypeIsDesc parameter specifies the form of the data to be coerced. If
  7961. its value is TRUE, the coercion handler expects the data to be passed as a
  7962. descriptor record. If its value is FALSE, the coercion handler expects a pointer
  7963. to the data to be coerced. Because it is more efficient for the Apple Event
  7964. Manager to provide a pointer to data than to a descriptor record, all coercion
  7965. routines should accept a pointer to data if possible.
  7966.  
  7967. The isSysHandler parameter specifies the coercion table to which to add the
  7968. handler. If its value is TRUE, the handler is added to the system coercion table
  7969. and made available to all applications. If its value is FALSE, the handler is
  7970. added to the application coercion table. Note that a handler in the system
  7971. coercion table must reside in the system heap; this means that if the value of
  7972. the isSysHandler parameter is TRUE, the handler parameter must point to a
  7973. location in the system heap.
  7974.  
  7975. If you put your handler code in the system heap or in your own heap, use the
  7976. AERemoveCoercionHandler function to remove the handler when your application
  7977. quits.
  7978.  
  7979.    Note: When an application calls a system Apple event handler, the A5 register
  7980.    is 
  7981.    set up for the calling application. For this reason, if you provide a system
  7982.    Apple 
  7983.    event handler, it should never use A5 global variables or anything that
  7984.    depends 
  7985.    on a particular context; otherwise, the application that calls the system
  7986.    handler 
  7987.    may crash.
  7988.  
  7989.    Result codes
  7990.           noErr                                      0      No error
  7991.           memFullErr                   –108      Not enough room in heap zone
  7992.  
  7993. The AEGetCoercionHandler function returns the handler for a specified descriptor
  7994. type coercion.
  7995.  
  7996. FUNCTION AEGetCoercionHandler (fromType: DescType; toType: DescType; 
  7997.                                VAR handler: ProcPtr; VAR handlerRefcon: 
  7998.                                LongInt; VAR fromTypeIsDesc: Boolean; 
  7999.                                isSysHandler: Boolean) : OSErr;
  8000.  
  8001. The fromType parameter is the descriptor type of the data coerced by the
  8002. handler, while the parameter toType is the descriptor type of the resulting
  8003. data.
  8004.  
  8005. The function returns a pointer to the coercion handler routine in the handler
  8006. parameter.
  8007.  
  8008. The function returns a reference constant in the handlerRefcon parameter. The
  8009. Apple Event Manager passes this reference constant to the handler each time the
  8010. handler is called.
  8011.  
  8012. If the function returns TRUE in the fromTypeIsDesc parameter, the coercion
  8013. handler expects the data to be passed as a descriptor record. If the function
  8014. returns FALSE, the coercion handler expects a pointer to the data.
  8015.  
  8016. The isSysHandler parameter specifies the coercion table from which to get the
  8017. handler. If its value is TRUE, the handler is taken from the system coercion
  8018. table. If its value is FALSE, the handler is taken from the application coercion
  8019. table.
  8020.  
  8021.    Result codes
  8022.           noErr                                                0      No error
  8023.           memFullErr                             –108      Not enough room in
  8024.           heap zone
  8025.           errAEHandlerNotFound    –1717      No handler found for an Apple event
  8026.           or 
  8027.                                                                              a
  8028.  
  8029.  
  8030.  
  8031. The AERemoveCoercionHandler function removes a coercion handler routine from
  8032. either the application or system coercion table.
  8033.  
  8034. FUNCTION AERemoveCoercionHandler (fromType: DescType; toType: DescType; 
  8035.                                   handler: ProcPtr; isSysHandler: 
  8036.                                   Boolean) : OSErr;
  8037.  
  8038. The fromType parameter is the descriptor type of the data coerced by the
  8039. handler.
  8040.  
  8041. The toType parameter is the descriptor type of the resulting data.
  8042.  
  8043. The handler parameter is a pointer to the coercion handler routine. Although the
  8044. fromType and toType parameters would be sufficient to identify the handler to be
  8045. removed, providing the handler parameter is a safeguard to ensure that you
  8046. remove the correct handler.
  8047.  
  8048. The isSysHandler parameter specifies the coercion table from which to remove the
  8049. handler. If its value is TRUE, the handler is removed from the system coercion
  8050. table. If its value is FALSE, the handler is removed from the application
  8051. coercion table.
  8052.  
  8053.    Result codes
  8054.           noErr                                                0      No error
  8055.           memFullErr                             –108      Not enough room in
  8056.           heap zone
  8057.           errAEHandlerNotFound    –1717      No handler found for an Apple event
  8058.           or 
  8059.                                                                              a
  8060.  
  8061.  
  8062. _______________________________________________________________________________
  8063.  
  8064. æKY Creating…and…Managing…the…Special…Handler…Tables
  8065. æC »Creating and Managing the Special Handler Tables               The Apple Event Manager
  8066. _______________________________________________________________________________
  8067.  
  8068. The AEInstallSpecialHandler function installs a handler in a special handler
  8069. table.
  8070.  
  8071. FUNCTION AEInstallSpecialHandler (functionClass: AEKeyword; handler: 
  8072.                                   ProcPtr; isSystemHandler: Boolean) : 
  8073.                                   OSErr;
  8074.  
  8075. The functionClass parameter is the keyword for the special handler that’s
  8076. installed. There is currently only one value allowed for this parameter: the
  8077. keyPreDispatch constant, which identifies a handler routine that is called
  8078. immediately before the Apple Event Manager dispatches an Apple event. If there
  8079. was already an entry in the specified special handler table for the same value
  8080. of functionClass, it is replaced.
  8081.  
  8082. The handler parameter is a pointer to the special handler. Note that a handler
  8083. in the system handler table must reside in the system heap; this means that if
  8084. the value of the isSysHandler parameter is TRUE, the handler parameter must
  8085. point to a location in the system heap.
  8086.  
  8087. The isSystemHandler parameter specifies the special handler table to which to
  8088. add the handler. If its value is TRUE, the handler is added to the system
  8089. handler table and made available to all applications. If its value is FALSE, the
  8090. handler is added to the application handler table.
  8091.  
  8092. If you put your handler code in the system heap or in your own heap, use the
  8093. AERemoveSpecialHandler function to remove the handler when your application
  8094. quits.
  8095.  
  8096.    Note:  When an application calls a system Apple event handler, the A5
  8097.    register is
  8098.    set up for the calling application. For this reason, if you provide a system
  8099.    Apple 
  8100.    event handler, it should never use A5 global variables or anything that
  8101.    depends 
  8102.    on a particular context; otherwise, the application that calls the system
  8103.    handler 
  8104.    may crash.
  8105.  
  8106.    Result codes
  8107.           noErr                                                    0      No
  8108.           error
  8109.           paramErr                                         –50      Parameter
  8110.           error (handler pointer is 
  8111.                                                                                
  8112.                                                                                
  8113.                                                                                
  8114.  
  8115.           memFullErr                                  –108      Not enough room
  8116.           in heap zone
  8117.           errAENotASpecialFunction    –1714      Wrong keyword for a special
  8118.           function
  8119.  
  8120. The AEGetSpecialHandler function returns a specified special handler.
  8121.  
  8122. FUNCTION AEGetSpecialHandler (functionClass: AEKeyword; VAR handler: 
  8123.                               ProcPtr; isSystemHandler: Boolean) : 
  8124.                               OSErr;
  8125.  
  8126. The functionClass parameter is the keyword that specifies the desired special
  8127. handler. There is currently only one value allowed for this parameter: the
  8128. keyPreDispatch constant, which identifies a handler routine that is called
  8129. immediately before the Apple Event Manager dispatches an Apple event.
  8130.  
  8131. The function returns a pointer to the special handler in the handler parameter.
  8132.  
  8133. The isSystemHandler parameter specifies the special handler table from which to
  8134. get the handler. If its value is TRUE, the handler is taken from the system
  8135. handler table. If its value is FALSE, the handler is taken from the application
  8136. handler table.
  8137.  
  8138.    Result codes
  8139.           noErr                                                    0      No
  8140.           error
  8141.           memFullErr                                  –108      Not enough room
  8142.           in heap zone
  8143.           errAENotASpecialFunction    –1714      Wrong keyword for a special
  8144.           function
  8145.  
  8146. The AERemoveSpecialHandler function removes a handler from a special handler
  8147. table.
  8148.  
  8149. FUNCTION AERemoveSpecialHandler (functionClass: AEKeyword; handler: ProcPtr; 
  8150.                                  isSystemHandler: Boolean) : OSErr;
  8151.  
  8152. The functionClass parameter is the keyword for the special handler to be
  8153. removed. There is currently only one value allowed for the functionClass
  8154. parameter: the keyPreDispatch constant, which identifies a handler routine that
  8155. is called immediately before the Apple Event Manager dispatches an Apple event.
  8156.  
  8157. The handler parameter is a pointer to the special handler to be removed.
  8158. Although the functionClass parameter would be sufficient to identify the handler
  8159. to be removed, providing the handler parameter is a safeguard to ensure that you
  8160. remove the correct handler.
  8161.  
  8162. The isSystemHandler parameter specifies the special handler table from which to
  8163. remove the handler. If its value is TRUE, the handler is taken from the system
  8164. handler table. If its value is FALSE, the handler is removed from the
  8165. application handler table.
  8166.  
  8167.    Result codes
  8168.           noErr                                                    0       No
  8169.           error
  8170.           memFullErr                                  –108      Not enough room
  8171.           in heap zone
  8172.           errAENotASpecialFunction    –1714      Wrong keyword for a special
  8173.           function
  8174. _______________________________________________________________________________
  8175.  
  8176. æKY Summary…of…the…Apple…Events…Manager…Volume…VI
  8177. æC »Summary of the Apple Events Manager Volume VI                  The Apple Event Manager
  8178. _______________________________________________________________________________
  8179.  
  8180. Click the arrow in the lower-right corner of this window to see the summary
  8181. sections of the constants, data types, and routines for the Apple Event Manager.
  8182.  
  8183.  
  8184.  
  8185. _______________________________________________________________________________
  8186.  
  8187. æKY Apple…Events…Manager…Constants
  8188. æC »Apple Events Manager Constants                                 The Apple Event Manager
  8189. _______________________________________________________________________________
  8190.  
  8191. CONST  gestaltAppleEventsAttr  = 'evnt';     {selector for Apple events}
  8192.        gestaltAppleEventsPresent
  8193.                                = 0;          {if set, Apple Event }
  8194.                                              { Manager is available}
  8195.  
  8196.        {Apple event descriptor types}
  8197.        typeBoolean             = 'bool';     {Boolean value}
  8198.        typeChar                = 'TEXT';     {unterminated string}
  8199.        typeSMInt               = 'shor';     {16-bit integer}
  8200.        typeInteger             = 'long';     {32-bit integer}
  8201.        typeSMFloat             = 'sing';     {SANE Single}
  8202.        typeFloat               = 'doub';     {SANE Double}
  8203.        typeLongInteger         = 'long';     {32-bit integer}
  8204.        typeShortInteger        = 'shor';     {16-bit integer}
  8205.        typeLongFloat           = 'doub';     {SANE Double}
  8206.        typeShortFloat          = 'sing';     {SANE Single}
  8207.        typeExtended            = 'exte';     {SANE Extended}
  8208.        typeComp                = 'comp';     {SANE Comp}
  8209.        typeMagnitude           = 'magn';     {unsigned 32-bit integer}
  8210.        typeAEList              = 'list';     {list of descriptor records}
  8211.        typeAERecord            = 'reco';     {list of keyword-specified }
  8212.                                              { descriptor records}
  8213.        typeAppleEvent          = 'aevt'      {Apple event record}
  8214.        typeTrue                = 'true';     {TRUE Boolean value}
  8215.        typeFalse               = 'fals';     {FALSE Boolean value}
  8216.        typeAlias               = 'alis';     {alias record}
  8217.        typeEnumerated          = 'enum';     {enumerated data}
  8218.        typeType                = 'type';     {descriptor type}
  8219.        typeAppParameters       = 'appa';     {Process Manager launch }
  8220.                                              { parameters}
  8221.        typeProperty            = 'prop';     {Apple event property}
  8222.        typeFSS                 = 'fss ';     {file system specification}
  8223.        typeKeyword             = 'keyw';     {Apple event keyword}
  8224.        typeSectionH            = 'sect';     {Edition Manager section }
  8225.                                              { handle}
  8226.        typeTemporaryID         = 'tid '      {temporary ID}
  8227.        typeWildCard            = '****';     {matches any type}
  8228.        typeApplSignature       = 'sign';     {application signature}
  8229.        typeSessionID           = 'ssid';     {session ID}
  8230.        typeTargetID            = 'targ';     {target ID}
  8231.        typeProcessSerialNumber
  8232.                                = 'psn ';     {process serial number}
  8233.        typeNull                = 'null';     {NULL or nonexistent data}
  8234.  
  8235.        {keywords for Apple event parameters}
  8236.        keyDirectObject         = '----';     {direct parameter}
  8237.        keyErrorNumber          = 'errn';     {error number parameter}
  8238.        keyErrorString          = 'errs';     {error string parameter}
  8239.        keyProcessSerialNumber  = 'psn ';     {process serial number param}
  8240.  
  8241.        {keywords for Apple event attributes}
  8242.        keyTransactionIDAttr    = 'tran';     {transaction ID}
  8243.        keyReturnIDAttr         = 'rtid';     {return ID}
  8244.        keyEventClassAttr       = 'evcl';     {event class}
  8245.        keyEventIDAttr          = 'evid';     {event ID}
  8246.        keyAddressAttr          = 'addr';     {target application}
  8247.        keyOptionalKeywordAttr  = 'optk';     {list of optional }
  8248.                                              { parameters for the }
  8249.                                              { Apple event}
  8250.        keyTimeoutAttr          = 'timo';     {number of ticks the client }
  8251.         { will wait}
  8252.        keyInteractLevelAttr    = 'inte';     {settings to allow Apple }
  8253.                                              { Event Mgr to bring }
  8254.                                              { server to foreground}
  8255.        keyEventSourceAttr      = 'esrc';     {source application}
  8256.        keyMissedKeywordAttr    = 'miss';     {first required parameter }
  8257.                                              { remaining in an Apple }
  8258.                                              { event}
  8259.  
  8260.        {keywords for special handlers}
  8261.        keyPreDispatch          = 'phac';     {identifies a handler }
  8262.                                              { routine that is called }
  8263.                                              { immediately before the }
  8264.                                              { Apple Event Manager }
  8265.                                              { dispatches an Apple event}
  8266.  
  8267.        {event classes}
  8268.        kCoreEventClass         = 'aevt';     {event class for core }
  8269.                                              { Apple events}
  8270.  
  8271.        {event IDs}
  8272.        kAEApplicationDied       = 'obit'     {event ID for Application }
  8273.                                              { Died event}
  8274.        kAEOpenApplication       = 'oapp';    {event ID for Open }
  8275.                                              { Application event}
  8276.        kAEOpenDocuments         = 'odoc';    {event ID for Open }
  8277.                                              { Documents event}
  8278.        kAEPrintDocuments        = 'pdoc';    {event ID for Print }
  8279.                                              { Documents event}
  8280.        kAEQuitApplication       = 'quit';    {event ID for Quit }
  8281.                                              { Application event}
  8282.        kAEAnswer                = 'ansr';    {event ID for Apple event }
  8283.                                              { replies}
  8284.  
  8285.        {constants for setting the sendMode parameter of AESend and for }
  8286.        { the keyInteractLevelAttr attribute}
  8287.        kAENoReply               = $00000001; {client doesn't want a reply}
  8288.        kAEQueueReply            = $00000002; {client wants server to }
  8289.                                              { reply in event queue}
  8290.        kAEWaitReply             = $00000003; {client wants a reply and }
  8291.                                              { will give up processor}
  8292.        kAENeverInteract         = $00000010; {server application should }
  8293.                                              { not interact with user }
  8294.                                              { for this Apple event}
  8295.        kAECanInteract           = $00000020; {server may interact with }
  8296.                                              { user for this Apple }
  8297.                                              { to supply information}
  8298.                                              { event}
  8299.        kAEAlwaysInteract        = $00000030; {server may interact with }
  8300.                                              { user for this Apple event }
  8301.                                              { even if no information }
  8302.                                              { is required}
  8303.        kAECanSwitchLayer        = $00000040; {server should come }
  8304.                                              { directly to foreground }
  8305.                                              { when appropriate}
  8306.        kAEDontReconnect         = $00000080; {don't reconnect if there }
  8307.                                              { is a PPC sessClosedErr}
  8308.        kAEWantReceipt           = nReturnReceipt;
  8309.                                              {client wants return receipt}
  8310.  
  8311.        {constants for the sendPriority parameter of AESend}
  8312.        kAENormalPriority        = $00000000; {put event at the back of }
  8313.                                              { event queue}
  8314.        kAEHighPriority          = nAttnMsg;  {put event at the front of }
  8315.                                              { the event queue}
  8316.  
  8317.        {constant for the returnID parameter of AECreateAppleEvent}
  8318.        kAutoGenerateReturnID    = -1;        {tells Apple Event Manager }
  8319.                                              { to generate a unique }
  8320.                                              { return ID}
  8321.  
  8322.        {constant for transaction IDs}
  8323.        kAnyTransactionID        = 0;         {the Apple event is not }
  8324.                                              { part of a transaction}
  8325.  
  8326.        {constants for timeout durations}
  8327.        kAEDefaultTimeout        = -1;        {use default timeout value}
  8328.        kNoTimeOut               = -2;        {never time out}
  8329.  
  8330.        {constants for the dispatcher parameter of AEResumeTheCurrentEvent}
  8331.        kAENoDispatch            = 0;         {don't redispatch the }
  8332.                                              { Apple event}
  8333.        kAEUseStandardDispatch   = -1;        {redispatch the Apple event }
  8334.                                              { by using its entry in the }
  8335.                                              { Apple event dispatch table}
  8336.           
  8337. _______________________________________________________________________________
  8338.  
  8339. æKY Apple…Events…Manager…Data…Types
  8340. æC »Apple Events Manager Data Types                                The Apple Event Manager
  8341. _______________________________________________________________________________
  8342.  
  8343. TYPE
  8344.      AEEventClass = 
  8345.         PACKED ARRAY[1..4] OF Char;           {event class for a }
  8346.                                               { high-level event}
  8347.      AEEventID = 
  8348.         PACKED ARRAY[1..4] OF Char;           {event ID for a high-level }
  8349.                                               { event}
  8350.      DescType                  = ResType;     {descriptor type}
  8351.  
  8352.      AEDesc = 
  8353.      RECORD                                   {descriptor record}
  8354.          descriptorType:       DescType;      {type of data being passed}
  8355.          dataHandle:           Handle          {handle to data being passed}
  8356.      END;
  8357.  
  8358.      AEKeyword = 
  8359.        PACKED ARRAY[1..4] OF Char;             {keyword for a descriptor}
  8360.  
  8361.      AEKeyDesc =                               {keyword-specified }
  8362.                                                { descriptor record}
  8363.      RECORD
  8364.         descKey:               AEKeyword;      {keyword}
  8365.         descContent:           AEDesc;         {descriptor record}
  8366.      END;
  8367.  
  8368.      AEAddressDesc             = AEDesc;       {descriptor containing an }
  8369.                                                { Apple event address}
  8370.  
  8371.      AEDescList                = AEDesc;       {list of descriptor records}
  8372.  
  8373.      AERecord                  = AEDescList;   {list of keyword-specified }
  8374.                                                { descriptor records}
  8375.  
  8376.      AppleEvent                = AERecord;     {list of attributes and }
  8377.                                                { parameters necessary for }
  8378.                                                { an Apple event}
  8379.      AESendMode                = LongInt;      {flags that determine how }
  8380.                                                { an Apple event is sent}
  8381.  
  8382.      AESendPriority            = Integer;      {send priority of an Apple }
  8383.                                                { event}
  8384.  
  8385.      AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal,
  8386.                           kAEInteractWithAll);
  8387.                                               {what processes may }
  8388.                                               { interact with the user}
  8389.  
  8390.      AEEventSource = (kAEUnknownSource, kAEDirectCall, kAESameProcess,
  8391.                       kAELocalProcess, kAERemoteProcess);
  8392.                                               {the source of an Apple }
  8393.                                               { event; the type of the }
  8394.                                               { keyEventSourceAttr }
  8395.                                               { attribute}
  8396.  
  8397.      AEArrayType = (kAEDataArray, kAEPackedArray, kAEHandleArray, 
  8398.                     kAEDescArray, kAEKeyDescArray);
  8399.                                               {type of an Apple event }
  8400.                                               { array}
  8401.  
  8402.      AEArrayData = 
  8403.      RECORD                                   {data for an Apple event }
  8404.                                               { array}
  8405.          case AEArrayType OF
  8406.          kAEDataArray:
  8407.          (AEDataArray:      ARRAY[0..0] OF Integer);
  8408.          kAEPackedArray:  
  8409.          (AEPackedArray:    PACKED ARRAY[0..0] OF Char);
  8410.          kAEHandleArray:  
  8411.          (AEHandleArray:    ARRAY[0..0] OF Handle);
  8412.          kAEDescArray:  
  8413.          (AEDescArray:      ARRAY[0..0] OF AEDesc);
  8414.          kAEKeyDescArray:  
  8415.          (AEKeyDescArray:   ARRAY[0..0] OF AEKeyDesc);
  8416.      END;
  8417.   
  8418.      AEArrayDataPointer = ^AEArrayData;
  8419.  
  8420.      EventHandlerProcPtr = ProcPtr;           {pointer to an Apple event }
  8421.                                               { handler routine}
  8422.  
  8423.      IdleProcPtr = ProcPtr;                   {pointer to an app's }
  8424.                                               { idle function}
  8425.  
  8426.      EventFilterProcPtr = ProcPtr;            {pointer to an app's filter }
  8427.                                               { procedure}
  8428. _______________________________________________________________________________
  8429.  
  8430. æKY Apple…Events…Manager…Routines…Summary
  8431. æC »Apple Events Manager Routines Summary                          The Apple Event Manager
  8432. _______________________________________________________________________________
  8433.  
  8434. Creating and Managing the Apple Event Dispatch Tables
  8435.  
  8436. FUNCTION AEInstallEventHandler  (theAEEventClass: AEEventClass;
  8437.                                  theAEEventID: AEEventID; handler:
  8438.                                  EventHandlerProcPtr; handlerRefcon:
  8439.                                  LongInt; isSysHandler: Boolean) : OSErr;
  8440.  
  8441. FUNCTION AEGetEventHandler      (theAEEventClass: AEEventClass; theAEEventID:
  8442.                                  AEEventID; VAR handler: EventHandlerProcPtr;
  8443.                                  VAR handlerRefcon: LongInt; isSysHandler:
  8444.                                  Boolean) : OSErr;
  8445.  
  8446. FUNCTION AERemoveEventHandler   (theAEEventClass: AEEventClass; theAEEventID:
  8447.                                  AEEventID; handler: EventHandlerProcPtr;
  8448.                                  isSysHandler: Boolean) : OSErr;
  8449.  
  8450.  
  8451. Dispatching Apple Events
  8452.  
  8453. FUNCTION AEProcessAppleEvent  (theEventRecord: EventRecord) : OSErr;
  8454.  
  8455.  
  8456. Getting Parameters and Attributes From Apple Events
  8457.  
  8458. FUNCTION AEGetParamPtr        (theAppleEvent: AppleEvent; theAEKeyword:
  8459.                                AEKeyword; desiredType: DescType;
  8460.                                VAR typeCode: DescType; dataPtr: Ptr;
  8461.                                maximumSize: Size; VAR actualSize: Size) : 
  8462.                                OSErr;
  8463.  
  8464. FUNCTION AEGetParamDesc      (theAppleEvent: AppleEvent; theAEKeyword: 
  8465.                               AEKeyword; desiredType: DescType; VAR result:
  8466.                               AEDesc) : OSErr;
  8467.  
  8468. FUNCTION AEGetAttributePtr   (theAppleEvent: AppleEvent; theAEKeyword: 
  8469.                               AEKeyword; desiredType: DescType; VAR typeCode:
  8470.                               DescType; dataPtr: Ptr; maximumSize: Size;
  8471.                               VAR actualSize: Size) : OSErr;
  8472.  
  8473. FUNCTION AEGetAttributeDesc  (theAppleEvent: AppleEvent; theAEKeyword: 
  8474.                               AEKeyword; desiredType: DescType; VAR result: 
  8475.                               AEDesc) : OSErr;
  8476.  
  8477. Counting the Items in Descriptor Lists
  8478.  
  8479. FUNCTION AECountItems        (theAEDescList: AEDescList; VAR theCount: 
  8480.                               LongInt) : OSErr;
  8481.  
  8482. Getting Items From Descriptor Lists
  8483.  
  8484. FUNCTION AEGetNthPtr         (theAEDescList: AEDescList; index: LongInt; 
  8485.                               desiredType: DescType; VAR theAEKeyword: 
  8486.                               AEKeyword; VAR typeCode: DescType; dataPtr:
  8487.                               Ptr; maximumSize: Size; VAR actualSize: Size) 
  8488.                               : OSErr;
  8489.  
  8490. FUNCTION AEGetNthDesc       (theAEDescList: AEDescList; index: LongInt;
  8491.                              desiredType: DescType; VAR theAEKeyword:
  8492.                              AEKeyword; VAR result: AEDesc) : OSErr;
  8493.  
  8494. FUNCTION AEGetArray         (theAEDescList: AEDescList; arrayType: 
  8495.                              AEArrayType; arrayPtr: AEArrayDataPointer; 
  8496.                              maximumSize: Size; VAR itemType: DescType; VAR 
  8497.                              itemSize: Size; VAR itemCount: LongInt) : OSErr;
  8498.  
  8499. Getting Data and Keyword-Specified Descriptor Records From AE Records
  8500.  
  8501. FUNCTION AEGetKeyPtr         (theAERecord: AERecord; theAEKeyword: AEKeyword;
  8502.                               desiredType: DescType; VAR typeCode: DescType; 
  8503.                               dataPtr: Ptr; maximumSize: Size;
  8504.                               VAR actualSize: Size) : OSErr;
  8505.  
  8506. FUNCTION AEGetKeyDesc        (theAERecord: AERecord; theAEKeyword: AEKeyword;
  8507.                               desiredType: DescType; VAR result: AEDesc) 
  8508.                               : OSErr;
  8509.  
  8510.  
  8511. Requesting User Interaction
  8512.  
  8513. FUNCTION AESetInteractionAllowed  (level: AEInteractAllowed) : OSErr;
  8514.  
  8515. FUNCTION AEInteractWithUser       (timeOutInTicks: LongInt; nmReqPtr: 
  8516.                                    QElemPtr; idleProc: IdleProcPtr) : OSErr;
  8517.  
  8518. FUNCTION AEGetInteractionAllowed  (VAR level: AEInteractAllowed) : OSErr;
  8519.  
  8520.  
  8521. Requesting More Time to Respond to Apple Events
  8522.  
  8523. FUNCTION AEResetTimer   (reply: AppleEvent) : OSErr;
  8524.  
  8525.  
  8526. Suspending and Resuming Apple Event Handling
  8527.  
  8528. FUNCTION AESuspendTheCurrentEvent  (theAppleEvent: AppleEvent) : OSErr;
  8529.  
  8530. FUNCTION AEResumeTheCurrentEvent   (theAppleEvent, reply: AppleEvent; 
  8531.                                     dispatcher: EventHandlerProcPtr; 
  8532.                                     handlerRefcon: LongInt) : OSErr;
  8533.  
  8534. FUNCTION AESetTheCurrentEvent      (theAppleEvent: AppleEvent) : OSErr;
  8535.  
  8536. FUNCTION AEGetTheCurrentEvent      (VAR theAppleEvent: AppleEvent): OSErr;
  8537.    
  8538.  
  8539. Creating Apple Events
  8540.  
  8541. FUNCTION AECreateAppleEvent        (theAEEventClass: AEEventClass; 
  8542.                                     theAEEventID: AEEventID; target: 
  8543.                                     AEAddressDesc; returnID: Integer; 
  8544.                                     transactionID: LongInt; VAR result: 
  8545.                                     AppleEvent) : OSErr;
  8546.  
  8547.  
  8548. Creating and Duplicating Descriptor Records
  8549.  
  8550. FUNCTION AECreateDesc          (typeCode: DescType; dataPtr: Ptr; dataSize: 
  8551.                                 Size; VAR result: AEDesc) : OSErr;
  8552.  
  8553. FUNCTION AEDuplicateDesc       (theAEDesc: AEDesc; VAR result: AEDesc)
  8554.                                 : OSErr;
  8555.  
  8556.  
  8557. Creating Descriptor Lists and AE Records
  8558.  
  8559. FUNCTION AECreateList          (factoringPtr: Ptr; factoredSize: Size; 
  8560.                                 isRecord: Boolean; VAR resultList: 
  8561.                                 AEDescList) : OSErr;
  8562.  
  8563.  
  8564. Adding Items to Descriptor Lists
  8565.  
  8566. FUNCTION AEPutPtr              (theAEDescList: AEDescList; index: LongInt; 
  8567.                                 typeCode: DescType; dataPtr: Ptr; dataSize: 
  8568.                                 Size) : OSErr;
  8569.  
  8570. FUNCTION AEPutDesc             (theAEDescList: AEDescList; index: LongInt; 
  8571.                                 theAEDesc: AEDesc) : OSErr;
  8572.  
  8573. FUNCTION AEPutArray            (theAEDescList: AEDescList; arrayType: 
  8574.                                 AEArrayType; arrayPtr: AEArrayDataPointer; 
  8575.                                 itemType: DescType; itemSize: Size; 
  8576.                                 itemCount: LongInt) : OSErr;
  8577.  
  8578.  
  8579. Adding Keyword-Specified Descriptor Records to AE Records
  8580.  
  8581. FUNCTION AEPutKeyPtr           (theAERecord: AERecord; theAEKeyword: 
  8582.                                 AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  8583.                                 dataSize: Size) : OSErr;
  8584.  
  8585. FUNCTION AEPutKeyDesc          (theAERecord: AERecord; theAEKeyword: 
  8586.                                 AEKeyword; theAEDesc: AEDesc) : OSErr;
  8587.  
  8588.  
  8589. Adding Parameters and Attributes to Apple Events
  8590.  
  8591. FUNCTION AEPutParamPtr         (theAppleEvent: AppleEvent; theAEKeyword: 
  8592.                                 AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  8593.                                 dataSize: Size) : OSErr;
  8594.  
  8595. FUNCTION AEPutParamDesc        (theAppleEvent: AppleEvent; theAEKeyword: 
  8596.                                 AEKeyword; theAEDesc: AEDesc) : OSErr;
  8597.  
  8598. FUNCTION AEPutAttributePtr     (theAppleEvent: AppleEvent; theAEKeyword:
  8599.                                 AEKeyword; typeCode: DescType; dataPtr: Ptr; 
  8600.                                 dataSize: Size) : OSErr;
  8601.  
  8602. FUNCTION AEPutAttributeDesc    (theAppleEvent: AppleEvent; theAEKeyword: 
  8603.                                 AEKeyword; theAEDesc: AEDesc) : OSErr;
  8604.  
  8605.  
  8606. Sending Apple Events
  8607.  
  8608. FUNCTION AESend                (theAppleEvent: AppleEvent; VAR reply: 
  8609.                                 AppleEvent; sendMode: AESendMode; 
  8610.                                 sendPriority: AESendPriority; timeOutInTicks: 
  8611.                                 LongInt; idleProc: IdleProcPtr; filterProc: 
  8612.                                 EventFilterProcPtr) : OSErr;
  8613.  
  8614.  
  8615. Getting the Sizes and Descriptor Types of Descriptor Records
  8616.  
  8617. FUNCTION AESizeOfNthItem      (theAEDescList: AEDescList; index: LongInt; VAR
  8618.                                typeCode: DescType; VAR dataSize: Size)
  8619.                                : OSErr;
  8620.  
  8621. FUNCTION AESizeOfKeyDesc      (theAERecord: AERecord; theAEKeyword: 
  8622.                                AEKeyword; VAR typeCode: DescType;
  8623.                                VAR dataSize: Size) : OSErr;
  8624.  
  8625. FUNCTION AESizeOfParam        (theAppleEvent: AppleEvent; theAEKeyword: 
  8626.                                AEKeyword; VAR typeCode: DescType;
  8627.                                VAR dataSize: Size) : OSErr;
  8628.  
  8629. FUNCTION AESizeOfAttribute    (theAppleEvent: AppleEvent; theAEKeyword: 
  8630.                                AEKeyword; VAR typeCode: DescType;
  8631.                                VAR dataSize: Size) : OSErr;
  8632.  
  8633.  
  8634. Deleting Descriptor Records
  8635.  
  8636. FUNCTION AEDeleteItem         (theAEDescList: AEDescList; index: LongInt)
  8637.                                : OSErr;
  8638.  
  8639. FUNCTION AEDeleteKeyDesc      (theAERecord: AERecord; theAEKeyword: 
  8640.                                AEKeyword) : OSErr;
  8641.  
  8642. FUNCTION AEDeleteParam        (theAppleEvent: AppleEvent; theAEKeyword: 
  8643.                                AEKeyword) : OSErr;
  8644.  
  8645.  
  8646. Deallocating Memory for Descriptor Records
  8647.  
  8648. FUNCTION AEDisposeDesc        (VAR theAEDesc: AEDesc) : OSErr;
  8649.  
  8650.  
  8651. Coercing Descriptor Types
  8652.  
  8653. FUNCTION AECoercePtr          (typeCode: DescType; dataPtr: Ptr; dataSize: 
  8654.                                Size; toType: DescType; VAR result: AEDesc)
  8655.                                : OSErr;
  8656.  
  8657. FUNCTION AECoerceDesc        (theAEDesc: AEDesc; toType: DescType;
  8658.                               VAR result: AEDesc) : OSErr;
  8659.  
  8660.  
  8661. Creating and Managing the Coercion Handler Tables
  8662.  
  8663. FUNCTION AEInstallCoercionHandler  (fromType: DescType; toType: DescType;
  8664.                                     handler: ProcPtr; handlerRefcon: LongInt;
  8665.                                     fromTypeIsDesc: Boolean; isSysHandler: 
  8666.                                     Boolean) : OSErr;
  8667.  
  8668. FUNCTION AEGetCoercionHandler      (fromType: DescType; toType: DescType;
  8669.                                     VAR handler: ProcPtr; VAR handlerRefcon: 
  8670.                                     LongInt; VAR fromTypeIsDesc: Boolean; 
  8671.                                     isSysHandler: Boolean) : OSErr;
  8672.  
  8673. FUNCTION AERemoveCoercionHandler   (fromType: DescType; toType: DescType; 
  8674.                                     handler: ProcPtr; isSysHandler: Boolean) 
  8675.                                     : OSErr;
  8676.  
  8677.  
  8678. Creating and Managing the Special Handler Tables
  8679.  
  8680. FUNCTION AEInstallSpecialHandler   (functionClass: AEKeyword; handler: 
  8681.                                     ProcPtr; isSystemHandler: Boolean)
  8682.                                     : OSErr;
  8683.  
  8684. FUNCTION AEGetSpecialHandler       (functionClass: AEKeyword; VAR handler:
  8685.                                     ProcPtr; isSystemHandler: Boolean)
  8686.                                     : OSErr;
  8687.  
  8688. FUNCTION AERemoveSpecialHandler    (functionClass: AEKeyword; handler: 
  8689.                                     ProcPtr; isSystemHandler: Boolean)
  8690.                                     : OSErr;
  8691.  
  8692.  
  8693. Application-Defined Routines
  8694.  
  8695. FUNCTION MyEventHandler         (theAppleEvent: AppleEvent; reply: 
  8696.                                  AppleEvent; handlerRefcon: LongInt) : OSErr; 
  8697.  
  8698. FUNCTION MyCoercePtr            (typeCode: DescType; dataPtr: Ptr; dataSize: 
  8699.                                  Size; toType: DescType; handlerRefcon: 
  8700.                                  LongInt; VAR result: AEDesc) : OSErr; 
  8701.  
  8702. FUNCTION MyCoerceDesc           (theAEDesc: AEDesc; toType: DescType; 
  8703.                                  handlerRefcon: LongInt; VAR result: AEDesc) 
  8704.                                  : OSErr;
  8705.  
  8706. FUNCTION MyIdleFunction         (VAR theEventRecord: EventRecord;
  8707.                                  VAR sleepTime: LongInt; VAR mouseRgn: 
  8708.                                  RgnHandle) : Boolean;
  8709.  
  8710. FUNCTION MyWaitReplyFilter      (VAR theEventRecord: EventRecord; 
  8711.                                  transactionID: LongInt; returnID: LongInt; 
  8712.                                  sender: AEAddressDesc) : Boolean;
  8713. _______________________________________________________________________________
  8714.  
  8715. æKY Apple…Events…Manager…Result…Codes
  8716. æC »Apple Events Manager Result Codes                              The Apple Event Manager
  8717. _______________________________________________________________________________
  8718.  
  8719. noErr                                                      0     No error
  8720. paramErr                                           –50     Parameter error
  8721. (handler pointer is NIL or 
  8722.                                                                         odd)
  8723. memFullErr                                    –108     Not enough room in heap
  8724. zone
  8725. bufferIsSmall                                  –607     Buffer is too small
  8726. noOutstandingHLE                       –608     No outstanding high-level event
  8727. connectionInvalid                         –609     Connection is invalid
  8728. errAECoercionFail                       –1700     Data could not be coerced to
  8729. the requested
  8730.  
  8731.                                                                          type
  8732. errAEDescNotFound                   –1701     Descriptor record was not found
  8733. errAECorruptData                        –1702     Data in an Apple event could
  8734. not be read
  8735. errAEWrongDataType                –1703     Wrong descriptor type
  8736. errAENotAEDesc                         –1704      Not a valid descriptor record
  8737. errAEBadListItem                        –1705     Operation involving a list
  8738. item failed
  8739. errAENewerVersion                   –1706     Need a newer version of the Apple
  8740. Event 
  8741.                                                                          Manager
  8742. errAENotAppleEvent                 –1707     Event is not an Apple event
  8743. errAEEventNotHandled            –1708     Event wasn’t handled by an Apple event
  8744.  
  8745.                                                                          handler
  8746. errAEReplyNotValid                  –1709     AEResetTimer was passed an invalid
  8747. reply
  8748. errAEUnknownSendMode       –1710     Invalid sending mode was passed
  8749. errAEWaitCanceled                    –1711     User canceled out of wait loop
  8750. for reply or 
  8751.                                                                          receipt
  8752. errAETimeout                              –1712     Apple event timed out
  8753. errAENoUserInteraction           –1713     No user interaction allowed
  8754. errAENotASpecialFunction     –1714     Wrong keyword for a special function
  8755. errAEParamMissed                     –1715     Handler did not get all required
  8756. parameters
  8757. errAEUnknownAddressType  –1716     Unknown Apple event address type
  8758. errAEHandlerNotFound           –1717     No handler found for an Apple event or
  8759.                                                                         coercion
  8760. errAEReplyNotArrived             –1718     Reply has not yet arrived
  8761. errAEIllegalIndex                        –1719     Not a valid list index
  8762. _______________________________________________________________________________
  8763.  
  8764. æKY Apple…Events…Manager…Assembly-Language…Information
  8765. æC »Apple Events Manager Assembly-Language Information             The Apple Event Manager
  8766. _______________________________________________________________________________
  8767.  
  8768. Trap Macros Requiring Routine Selectors
  8769.  
  8770. _Pack8
  8771.  
  8772.  
  8773. Selector           Routine
  8774.  
  8775.   $00                  AEInstallSpecialHandler
  8776.   $01                  AERemoveSpecialHandler
  8777.   $02                  AECoercePtr
  8778.   $03                  AECoerceDesc
  8779.   $04                  AEDisposeDesc
  8780.   $05                  AEDuplicateDesc
  8781.   $06                  AECreateList
  8782.   $07                  AECountItems
  8783.   $08                  AEPutPtr
  8784.   $09                  AEPutDesc
  8785.   $0A                 AEGetNthPtr
  8786.   $0B                 AEGetNthDesc
  8787.   $0C                 AEGetArray
  8788.   $0D                AEPutArray
  8789.   $0E                 AEDeleteItem
  8790.   $0F                 AEPutKeyPtr
  8791.   $0F                 AEPutParamPtr
  8792.   $10                 AEPutKeyDesc
  8793.   $10                 AEPutParamDesc
  8794.   $11                 AEGetParamPtr
  8795.   $11                 AEGetKeyPtr
  8796.   $12                 AEGetKeyDesc
  8797.   $12                 AEGetParamDesc
  8798.   $13                 AEDeleteKeyDesc
  8799.   $13                 AEDeleteParam
  8800.   $14                 AECreateAppleEvent
  8801.   $15                 AEGetAttributePtr
  8802.   $16                 AEPutAttributePtr
  8803.   $17                 AESend
  8804.   $18                 AEResumeTheCurrentEvent
  8805.   $19                 AEResetTimer
  8806.   $1A                AEGetTheCurrentEvent
  8807.   $1B                 AEProcessAppleEvent
  8808.   $1C                 AEInteractWithUser
  8809.   $1D                 AEGetInteractionAllowed
  8810.   $1E                 AESetInteractionAllowed
  8811.   $1F                 AEInstallEventHandler
  8812.   $20                 AERemoveEventHandler
  8813.   $21                 AEGetEventHandler
  8814.   $22                 AEInstallCoercionHandler
  8815.   $23                 AERemoveCoercionHandler
  8816.   $24                 AEGetCoercionHandler 
  8817.   $25                 AECreateDesc
  8818.   $26                 AEGetAttributeDesc
  8819.   $27                 AEPutAttributeDesc
  8820.   $28                 AESizeOfAttribute
  8821.   $29                 AESizeOfParam
  8822.   $29                 AESizeOfKeyDesc
  8823.   $2A                AESizeOfNthItem
  8824.   $2B                 AESuspendTheCurrentEvent
  8825.   $2C                 AESetTheCurrentEvent
  8826.   $2D                 AEGetSpecialHandler
  8827.  
  8828.  
  8829. _______________________________________________________________________________
  8830.  
  8831.  
  8832. æKY AppleTalkManager
  8833. æC 
  8834. _______________________________________________________________________________
  8835.  
  8836. APPLETALK MANAGER
  8837. _______________________________________________________________________________
  8838.  
  8839. About…Appletalk…Manager…Chapter…Volume…VI
  8840. About…the…Appletalk…Manager…Volume…VI
  8841.     Changes…to…the…Appletalk…Manager
  8842.     Appletalk…Protocols
  8843.     Device…Drivers,connection…Files,…&…the…LAP…Manager
  8844. Using…the…Appletalk…Manager…Volume…VI
  8845.     Determining…if…Appletalk…Phase…2…Drivers…Are…Present
  8846.     Deciding…Which…Appletalk…Protocol…to…Use
  8847. The….MPP…Driver…Volume…VI
  8848.     Getting…Information…About…the….MPP…Driver
  8849.     A…New…Nbp…Wildcard…Character
  8850. The…LAP…Manager…Volume…VI
  8851.     The…Appletalk…Transition…Queue
  8852.         Adding…and…Removing…Appletalk…Transition…Queue…Entries
  8853.         Sending…Messages…to…the…Appletalk…Transition…Queue
  8854.         How…the…Appletalk…Manager…Calls…Your…Queue…Entry
  8855.         Defining…Your…Own…Appletalk…Transition
  8856.     The…LAP…Manager…802.2…Protocol
  8857.     Attaching…and…Detaching…802.2…Protocol…Handlers
  8858. The….ATP…Driver…Volume…VI
  8859.     Canceling…All…Calls…to…the…Atpgetrequest…Function
  8860.     Setting…the…Timeout…Value…for…the…Atp…Release…Timer
  8861. The….XPP…Driver…Volume…VI
  8862.     Using…the….XPP…Driver…to…Obtain…Information…About…Zones
  8863.     Obtaining…Zone…Information
  8864. Appletalk…Data…Stream…Protocol…(adsp)…Volume…VI
  8865.     Using…ADSP
  8866.         The…ADSP…Connection…Control…Block
  8867.         The….DSP…Parameter…Block
  8868.         Opening…and…Maintaining…an…ADSP…Connection
  8869.         Creating…and…Using…a…Connection…Listener
  8870.         Writing…a…User…Routine…for…Connection…Events
  8871.     .DSP…Driver…Routines
  8872.         Establishing…&…Terminating…an…ADSP…Connection
  8873.         Establishing…&…Terminating…an…ADSP…Connection…(cont'd)
  8874.         Establishing…&…Terminating…an…ADSP…Connection…Listener
  8875.         Maintaining…an…ADSP…Connection
  8876. The….ENET…Driver…Volume…VI
  8877.     Providing…Your…Own…Ethernet…Driver
  8878.     Changing…the…Ethernet…Hardware…Address
  8879.     Opening…the….ENET…Driver
  8880.     Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  8881.     Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  8882.     Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  8883.         How…the….ENET…Driver…Calls…Your…Protocol…Handler
  8884.         How…Your…Protocol…Handler…Calls…the….ENET…Driver
  8885.     .ENET…Driver…Routines
  8886.         Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  8887.         Writing…and…Reading…Ethernet…Packets
  8888.         Adding…and…Removing…Ethernet…Multicast…Addresses
  8889. Summary…of…the…Appletalk…Manager…Volume…VI
  8890.     Appletalk…Manager…Constants
  8891.     Appletalk…Manager…Data…Types
  8892.     Appletalk…Manager…Routines…Summary
  8893.     Appletalk…Manager…Global…Variable
  8894.     Appletalk…Manager…Result…Codes
  8895.     Appletalk…Manager…Assembly-language…Information
  8896.     
  8897. About…The…AppleTalkManager…Chapter
  8898. AppleTalk…Protocols
  8899. AppleTalk…Transaction…Protocol
  8900. About…the…AppleTalk…Manager
  8901. Calling…the…AppleTalk…Manager…from…Pascal
  8902. New…AppleTalk…Manager…Pascal…Interface
  8903. Picking…a…Node…Address…in…the…Server…Range
  8904. Sending…Packets…to…One’s…Own…Node
  8905. ATP…Driver…Changes
  8906. Name…Binding…Protocol…Changes
  8907. Variable…Resources
  8908. Calling…the…AppleTalk…Manager…from…Assembly…Language
  8909. Extended…Protocol…Package…Driver
  8910. Calling…the….XPP…Driver
  8911. Protocol…Handlers…and…Socket…Listeners
  8912. Summary…of…the…AppleTalk…Manager
  8913.  
  8914. _______________________________________________________________________________
  8915.  
  8916.  
  8917.  
  8918. æKY About…Appletalk…Manager…Chapter…Volume…VI
  8919. æC »About Appletalk Manager Chapter Volume VI                            AppleTalk Manager
  8920. _______________________________________________________________________________
  8921.  
  8922. AppleTalk® is a communications network system including personal computer
  8923. workstations, computers acting as file servers and print servers, printers, and
  8924. a variety of types of communications hardware and software. The AppleTalk
  8925. Manager provides an interface to this communications network system for
  8926. applications running on Macintosh® computers. This chapter describes changes to
  8927. the AppleTalk Manager introduced since the publication of Inside Macintosh ,
  8928. Volume V, and included with system software version 7.0. This chapter
  8929. supplements the information in the AppleTalk Manager chapters of Inside
  8930. Macintosh, Volumes II and V.
  8931.  
  8932. This chapter describes 
  8933.  
  8934.   •  new routines for the .MPP, .ATP, and .XPP device drivers
  8935.  
  8936.   •  a new wildcard character for use with the Name-Binding Protocol
  8937.  
  8938.   •  a new operating-system queue, called the AppleTalk Transition Queue
  8939.  
  8940.   •  a new set of operating-system utilities, collectively called the LAP
  8941.   Manager
  8942.  
  8943.   •  the application interface routines provided by a new AppleTalk protocol,
  8944.   the
  8945.       AppleTalk Data Stream Protocol (ADSP)
  8946.  
  8947.   •  the .ENET driver and the routines your application can use to control this
  8948.       driver
  8949.  
  8950. Together with the AppleTalk Manager chapters of Volumes II and V, this chapter
  8951. describes the routines that your application can use to send and receive
  8952. information within an AppleTalk network system. Because the AppleTalk network
  8953. system includes both hardware and software—and because the software includes not
  8954. only the AppleTalk Manager but also file servers, print servers, internet
  8955. routers, drivers for circuit cards, and so forth—the information in Inside
  8956. Macintosh  constitutes only a small part of the body of literature documenting
  8957. AppleTalk.
  8958.  
  8959. For a detailed description of AppleTalk protocols, see Inside AppleTalk . For a
  8960. complete description of the LAP Manager, EtherTalk®, and alternate AppleTalk
  8961. connections, see the AppleTalk Connections Programmer’s Guide . To learn how to
  8962. install and operate an AppleTalk internet, see the AppleTalk Internet Router
  8963. Administrator’s Guide  and the AppleTalk Phase 2 Introduction and Upgrade Guide
  8964. . For an introduction to the hardware and software of an entire AppleTalk
  8965. network, see Understanding Computer Networks  and the AppleTalk Network System
  8966. Overview . For information on designing circuit cards and device drivers for
  8967. Macintosh computers, see Designing Cards and Drivers for the Macintosh Family .
  8968.  
  8969. The changes to AppleTalk other than ADSP and the LAP Manager are collectively
  8970. referred to as AppleTalk Phase 2. (When necessary for purposes of
  8971. differentiation, the previous version of AppleTalk is referred to in this
  8972. chapter as AppleTalk Phase 1.) The Phase 2 versions of the AppleTalk drivers are
  8973. included as part of system software version 7.0 and can be installed on any
  8974. Macintosh computer other than the Macintosh 128K, Macintosh 512K, Macintosh 512K
  8975. enhanced, and Macintosh XL computers. If you want to provide AppleTalk Phase 2
  8976. drivers with your product, you must obtain a license from Apple® Software
  8977. Licensing.
  8978.  
  8979. _______________________________________________________________________________
  8980.  
  8981. æKY About…the…Appletalk…Manager…Volume…VI
  8982. æC »About the Appletalk Manager Volume VI                                AppleTalk Manager
  8983. _______________________________________________________________________________
  8984.  
  8985. The AppleTalk Manager includes a number of protocols that are implemented in
  8986. various device drivers. The AppleTalk Manager also includes the LAP Manager
  8987. (which interfaces the AppleTalk link access protocols to the higher-level
  8988. AppleTalk protocols), and hardware device drivers for specific data links.
  8989. Software that supports AppleTalk data links is contained in files of type
  8990. 'adev', referred to as AppleTalk connection files . This section lists the new
  8991. features of AppleTalk, describes the organization of the AppleTalk Manager, and
  8992. briefly discusses what each component of the AppleTalk Manager does. 
  8993.  
  8994. _______________________________________________________________________________
  8995.  
  8996. æKY Changes…to…the…Appletalk…Manager
  8997. æC »Changes to the Appletalk Manager                                     AppleTalk Manager
  8998. _______________________________________________________________________________
  8999.  
  9000. The AppleTalk features that are new or improved include
  9001.  
  9002.   •  a new .MPP driver function that returns information about the .MPP driver
  9003.       (see “Getting Information About the .MPP Driver,” later in this chapter)
  9004.  
  9005.   •  a new Name-Binding Protocol (NBP) wildcard character that can substitute
  9006.   for
  9007.       one or more characters in AppleTalk names (see “A New NBP Wildcard
  9008.       Character”)
  9009.  
  9010.   •  the LAP Manager, a set of operating-system utilities that provide a
  9011.   standard
  9012.       interface between the AppleTalk protocols and the data links used by
  9013.       AppleTalk, such as LocalTalk®, EtherTalk, and TokenTalk® (see “The LAP
  9014.       Manager”)
  9015.  
  9016.   •  the AppleTalk Transition Queue, an operating-system queue that can notify
  9017.       your application each time an AppleTalk driver is opened or closed or each
  9018.       time certain other transitions occur (see “The AppleTalk Transition
  9019.       Queue”)
  9020.  
  9021.   •  an implementation of parts of the IEEE 802.2 protocol, which allows you to
  9022.       attach and detach your own protocol handlers for EtherTalk data packets
  9023.       (see
  9024.       “The LAP Manager 802.2 Protocol”)
  9025.  
  9026.   •  new .ATP driver functions that allow you to set a value for the .ATP
  9027.   release
  9028.       timer and to cancel all pending asynchronous calls to the the
  9029.       ATPGetRequest
  9030.       function for a specific socket (see “The .ATP Driver”)
  9031.  
  9032.   •  new .XPP driver functions that provide information from ZIP about zones
  9033.   (see
  9034.       “The .XPP Driver”)
  9035.  
  9036.   •  improvements to the AppleTalk protocols that allow a single network, other
  9037.       than LocalTalk, to contain more than one zone (see “Using the .XPP Driver
  9038.       to
  9039.       Obtain Zone Information”)
  9040.  
  9041.   •  the AppleTalk Data Stream Protocol (ADSP), which provides full-duplex data
  9042.       stream communications for use by applications (see “AppleTalk Data Stream
  9043.       Protocol”)
  9044.  
  9045.   •  the .ENET driver, an Ethernet driver for the EtherTalk NB card that is
  9046.       manufactured by Apple Computer, Inc. (see “The .ENET Driver”)
  9047. _______________________________________________________________________________
  9048.  
  9049. æKY Appletalk…Protocols
  9050. æC »Appletalk Protocols                                                  AppleTalk Manager
  9051. _______________________________________________________________________________
  9052.  
  9053. The AppleTalk Manager includes the following protocols:
  9054.  
  9055.   •  LocalTalk Link Access Protocol (LLAP)
  9056.  
  9057.   •  EtherTalk Link Access Protocol (ELAP)
  9058.  
  9059.   •  TokenTalk Link Access Protocol (TLAP)
  9060.  
  9061.   •  Datagram Delivery Protocol (DDP)
  9062.  
  9063.   •  Routing Table Maintenance Protocol (RTMP)
  9064.  
  9065.   •  AppleTalk Transaction Protocol (ATP)
  9066.  
  9067.   •  Name-Binding Protocol (NBP)
  9068.  
  9069.   •  AppleTalk Echo Protocol (AEP)
  9070.  
  9071.   •  Zone Information Protocol (ZIP)
  9072.  
  9073.   •  AppleTalk Session Protocol (ASP)
  9074.  
  9075.   •  AppleTalk Data Stream Protocol (ADSP)
  9076.  
  9077.   •  AppleTalk Filing Protocol (AFP)
  9078.  
  9079. The LocalTalk Link Access Protocol, EtherTalk Link Access Protocol, TokenTalk
  9080. Link Access Protocol, and other link access protocols provide interfaces between
  9081. the AppleTalk Manager and the different types of data link hardware used by
  9082. AppleTalk.
  9083.  
  9084.    Note:  The LocalTalk Link Access Protocol (LLAP) was originally called the
  9085.    AppleTalk Link Access Protocol (ALAP). With the addition of the EtherTalk
  9086.    Link
  9087.    Access Protocol (ELAP) and other link access protocols, this protocol was
  9088.    renamed
  9089.    to indicate the specific data link it supports.
  9090.  
  9091. Figure 32-1 shows the relationships among the various AppleTalk protocols. A
  9092. line going from a protocol to another protocol above or below it in the figure
  9093. indicates that the upper protocol is a client of the lower protocol; that is,
  9094. the upper protocol uses services provided by the lower protocol in order to
  9095. carry out some functions.
  9096.  
  9097. ¿ Figure 32-1   AppleTalk protocols ø 
  9098.  
  9099.    Note:  The various AppleTalk protocols are sets of rules, not computer
  9100.    programs,
  9101.    and so can be implemented in many different ways on many different systems.
  9102.    All of the AppleTalk protocol functions that you can address or control from
  9103.    a
  9104.    Macintosh application are implemented as Macintosh device drivers or
  9105.    managers. Many other features of these protocols are implemented in software
  9106.    located only on internet routers that are not used to run general
  9107.    applications.
  9108.    Some parts of protocols are implemented by server software such as file
  9109.    servers
  9110.    and print servers. Therefore, when this chapter refers to a protocol as
  9111.    “doing” or
  9112.    “controlling” something, you should understand the statement to mean that
  9113.    some program that implements the protocol actually carries out the operation.
  9114.  
  9115. As shown in Figure 32-1, a link access protocol controls the access of the node
  9116. to the network hardware and makes it possible for many nodes to share the same
  9117. communications hardware. Each link access protocol assigns a node ID to the node
  9118. and decodes the node addresses of messages it receives. A link access protocol
  9119. provides node-to-node delivery of data packets. Examples of link access
  9120. protocols include the LocalTalk Link Access Protocol, the EtherTalk Link Access
  9121. Protocol, and the TokenTalk Link Access Protocol. 
  9122.  
  9123. Whereas earlier implementations of AppleTalk were restricted to one 16-bit
  9124. network number per network (that is, one network number for all nodes connected
  9125. with no intervening routers) and 254 nodes per network number, AppleTalk Phase 2
  9126. allows more than one network number for each network (other than LocalTalk,
  9127. which is still limited to one network number per network). A network of a type
  9128. that allows more than one network number is known as an extended network. Each
  9129. node in an extended network must now be specified by both its 16-bit network
  9130. number and its 8-bit node ID. In principle, each network (other than LocalTalk)
  9131. can now have over 16 million  (224) nodes. In any specific implementation, the
  9132. hardware or software might limit the network to fewer nodes.
  9133.  
  9134. The Datagram Delivery Protocol (DDP) provides socket-to-socket delivery of data
  9135. packets within an AppleTalk internet. The address of a DDP packet includes the
  9136. socket number, node ID, and network number. Application interface routines for
  9137. DDP are described in “Datagram Delivery Protocol” in the AppleTalk Manager
  9138. chapter of Volume II.
  9139.  
  9140. The Routing Table Maintenance Protocol (RTMP) is used by routers on an AppleTalk
  9141. internet to determine how to forward a data packet to the network number to
  9142. which it is addressed. The RTMP implementation on a router maintains a table,
  9143. called a routing table, that specifies the shortest path to each possible
  9144. destination network number. The AppleTalk protocol software in a workstation
  9145. (that is, a node other than a router) contains only a small part of RTMP, called
  9146. the RTMP stub, that DDP uses to determine the network number (or range of
  9147. network numbers) of the network cable to which the node is connected and to
  9148. determine the network number and node ID of one router on that network cable.
  9149. There is no application interface to the RTMP stub.
  9150.  
  9151. The AppleTalk Transaction Protocol (ATP) provides reliable delivery of data by
  9152. retransmitting any data packets that are lost. ATP also ensures that data
  9153. packets are delivered in the correct sequence. ATP is a transaction-based
  9154. protocol, meaning that one socket client transmits a request for some action and
  9155. the other socket client carries out the action and transmits a response.
  9156. Although—as you can see from Figure 32-1—the AppleTalk Manager provides
  9157. high-level protocols that are clients of ATP, many applications use ATP directly
  9158. to transmit data over an AppleTalk internet. The application interface to ATP is
  9159. described in the AppleTalk Manager chapter of Volume II. There are some
  9160. enhancements to ATP in AppleTalk Phase 2, described in “The .ATP Driver” later
  9161. in this chapter.
  9162.  
  9163. The Name-Binding Protocol (NBP) maintains a table that contains the internet
  9164. address and name of each entity in the node that is visible to other entities on
  9165. the internet (that is, each entity that has registered a name with NBP). The
  9166. internet address includes the socket number, node ID, and network number. The
  9167. name consists of three fields: the object, type, and zone. The object and type
  9168. are assigned by the entity itself and can be anything the user or application
  9169. assigns. A zone is a logical grouping of a subset of the nodes on the internet.
  9170. The zone field of the name is the zone in which the node resides.
  9171.  
  9172. NBP also allows its clients to obtain the internet address of any
  9173. network-visible entity in the internet by providing its name. NBP maps this name
  9174. to an internet address, thus providing the link between the user-supplied name
  9175. for an entity and the internet address that is used by DDP to send and receive
  9176. data packets. The application interface to NBP is described in the AppleTalk
  9177. Manager chapter of Volume II. There is one enhancement to NBP in AppleTalk Phase
  9178. 2, described in “A New NBP Wildcard Character” later in this chapter.
  9179.  
  9180. The AppleTalk Echo Protocol (AEP) listens for special packets sent by other
  9181. nodes and, when it receives such a packet, echoes it back to the sender. AEP is
  9182. used by some clients of DDP to determine whether another node (known to have
  9183. AEP) can be accessed over the internet, and to determine how long it takes a
  9184. packet to reach another node. There is no application interface to AEP.
  9185.  
  9186. The Zone Information Protocol (ZIP) maintains a table in each router, called the
  9187. zone information table, that lists the relationships between zone names and
  9188. networks. In AppleTalk Phase 2, a single network number can be associated with
  9189. more than one zone name, or a single zone name can be associated with more than
  9190. one network. You can use .XPP driver routines to obtain information from ZIP.
  9191. These routines are discussed in “Using the .XPP Driver to Obtain Information
  9192. About Zones” later in this chapter.
  9193.  
  9194. The AppleTalk Session Protocol (ASP) sets up and maintains sessions between a
  9195. workstation and a server. A session consists of a logical (as opposed to
  9196. physical) connection between two entities on the internet. ASP is a
  9197. nonsymmetrical protocol; that is, only one of the two entities involved in the
  9198. session (the workstation) can send commands. The other entity (the server) is
  9199. restricted to responding to the commands. ASP is used by the AppleTalk Filing
  9200. Protocol, for example, to allow a user to manipulate files on a file server. As
  9201. long as the session is open, the workstation can request directory information,
  9202. change filenames, and so forth. The file server must respond to the
  9203. workstation’s commands and cannot initiate any actions on its own. ASP is
  9204. discussed in the AppleTalk Manager chapter of Volume V.
  9205.  
  9206. The AppleTalk Data Stream Protocol (ADSP) appears to its clients to maintain an
  9207. open pipeline between two entities on the internet. Either entity can write a
  9208. stream of bytes to the pipeline or read data bytes from the pipeline. ADSP is a
  9209. symmetrical protocol; that is, the two clients at either end of the connection
  9210. are equal and can perform exactly the same operations. ADSP is especially useful
  9211. for exchanging information between two equal entities, as in a telephone
  9212. communications network, or as required by a terminal emulation program for
  9213. sending or receiving a continuous stream of data. Because ADSP, like all other
  9214. high-level AppleTalk protocols is a client of DDP, the data is actually sent as
  9215. data packets. This allows ADSP to correct transmission errors in a way that
  9216. would not be possible for a true data stream connection. Thus, ADSP retains many
  9217. of the advantages of a transaction-based protocol while providing to its clients
  9218. a full-duplex data stream. ADSP is discussed in the sections “Using ADSP” and
  9219. “.DSP Driver Routines” later in this chapter.
  9220.  
  9221. The AppleTalk Filing Protocol (AFP) provides an interface between an application
  9222. and a file server. AFP is a client of ASP and is used to access AppleShare® file
  9223. servers on Macintosh computer workstations. When the user opens a session with
  9224. an AppleShare file server over an internet, it appears to any application
  9225. running on the workstation that uses File Manager routines as if the files on
  9226. the file server were located on a disk drive connected to the workstation. The
  9227. application interface to AFP is described in the AppleTalk Manager chapter of
  9228. Volume V. 
  9229.  
  9230. _______________________________________________________________________________
  9231.  
  9232. æKY Device…Drivers,connection…Files,…&…the…LAP…Manager
  9233. æC »Device Drivers,connection Files, & the LAP Manager                   AppleTalk Manager
  9234. _______________________________________________________________________________
  9235.  
  9236. A protocol is only a set of rules, not a computer program. The various AppleTalk
  9237. protocols are implemented as Macintosh device drivers, including
  9238.  
  9239.   •  the .MPP driver, which implements LLAP, DDP, the RTMP stub, NBP, and AEP
  9240.  
  9241.   •  the .ATP driver, which implements ATP
  9242.  
  9243.   •  the .XPP driver, which implements ASP and the workstation portions of ZIP
  9244.       and AFP
  9245.  
  9246.   •  the .DSP driver, which implements ADSP
  9247.  
  9248.   •  the .ENET driver, which implements an interface to the Ethernet data link
  9249.  
  9250. A Macintosh computer on an AppleTalk network can also include one or more
  9251. AppleTalk connection files. An AppleTalk connection file has file type 'adev'
  9252. and contains a link access protocol implementation for a data link (ELAP for
  9253. EtherTalk, for example). The LAP Manager makes it possible for the user to
  9254. select among AppleTalk connection files by using the Network control panel to
  9255. specify which network is to be used for the node’s AppleTalk connection. The
  9256. AppleTalk connection file and LAP Manager work together with the Network control
  9257. panel (Network 'cdev') file. When the user selects a connection from the Network
  9258. control panel, the LAP Manager routes AppleTalk communications through the
  9259. selected link access protocol and hence through the selected hardware.
  9260.  
  9261. The AppleTalk device drivers, LAP Manager, and AppleTalk connection files are
  9262. shown in Figure 32-2. As you can see from the figure, each device driver
  9263. implements one or more AppleTalk protocols.
  9264.  
  9265. ¿ Figure 32-2   AppleTalk device drivers ø 
  9266.  
  9267. Figure 32-3 shows the interfaces between a general application on a Macintosh
  9268. computer being used as an AppleTalk workstation and the AppleTalk protocols, the
  9269. LAP Manager, and the Ethernet hardware device driver. The lines connecting the
  9270. application to the various components of AppleTalk indicate which components
  9271. have application interfaces. As discussed in the preceding section, “AppleTalk
  9272. Protocols,” each application interface is described, at least in part, in this
  9273. or another volume of Inside Macintosh . 
  9274.  
  9275. ¿ Figure 32-3   AppleTalk application interfaces ø 
  9276.  
  9277.  
  9278. _______________________________________________________________________________
  9279.  
  9280. æKY Using…the…Appletalk…Manager…Volume…VI
  9281. æC »Using the Appletalk Manager Volume VI                                AppleTalk Manager
  9282. _______________________________________________________________________________
  9283.  
  9284. This section describes how to determine whether AppleTalk Phase 2 drivers are
  9285. present and gives some advice on how to select the AppleTalk protocol that best
  9286. serves your purposes. This section also describes how to use the features added
  9287. to AppleTalk with Phase 2 and provides programming examples of the use of the
  9288. .DSP driver and several other new AppleTalk features.
  9289.  
  9290. _______________________________________________________________________________
  9291.  
  9292. æKY Determining…if…Appletalk…Phase…2…Drivers…Are…Present
  9293. æC »Determining if Appletalk Phase 2 Drivers Are Present                 AppleTalk Manager
  9294. _______________________________________________________________________________
  9295.  
  9296. Once the .MPP driver has been loaded into memory, you can use the Gestalt
  9297. function with the gestaltAppleTalkVersion selector to check the version of
  9298. AppleTalk. The Gestalt function returns the version of the .MPP driver. If the
  9299. version is equal to or greater than 53, then the .MPP driver supports AppleTalk
  9300. Phase 2, and you can assume the other Phase 2 drivers are present.
  9301.  
  9302. Alternatively, you can call the SysEnvirons function as described in the
  9303. Compatibility Guidelines chapter of Volume V. If the atDrvrVersNum field of the
  9304. SysEnvRec data structure returned by this function is equal to or greater than
  9305. 53, then the .MPP driver supports AppleTalk Phase 2.
  9306.  
  9307. The ExtendedBit flag returned by the pGetAppleTalkInfo function is TRUE if the
  9308. node is connected to an extended AppleTalk network. (The ExtendedBit flag is bit
  9309. 15 of the configuration parameter returned by this function.) Note that the
  9310. presence of the AppleTalk Phase 2 drivers does not of itself indicate that the
  9311. node is connected to an extended network. 
  9312.  
  9313. _______________________________________________________________________________
  9314.  
  9315. æKY Deciding…Which…Appletalk…Protocol…to…Use
  9316. æC »Deciding Which Appletalk Protocol to Use                             AppleTalk Manager
  9317. _______________________________________________________________________________
  9318.  
  9319. AppleTalk offers a variety of communications protocols at a variety of levels.
  9320. Your choice of protocol or protocols to use depends primarily on your needs and
  9321. can be influenced by your familiarity with network communications in general. 
  9322.  
  9323. You can write your own protocol handlers and call the low-level AppleTalk device
  9324. drivers directly. However, if you are not a communications expert and have no
  9325. desire to design your own network protocols, you should probably use one of
  9326. three AppleTalk protocols for sending and receiving data over the AppleTalk
  9327. internet: the AppleTalk Transaction Protocol (ATP), the AppleTalk Session
  9328. Protocol (ASP), or the AppleTalk Data Stream Protocol (ADSP). 
  9329.  
  9330. ATP is a lower-level protocol than ASP or ADSP. You cannot use ATP to establish
  9331. a session and keep it open; rather, you request data from another socket client
  9332. or send a response (up to eight packets of data) from your socket to another
  9333. socket client that has requested data. You should use ATP if you want only to
  9334. send a small amount of data and do not need the overhead required to maintain an
  9335. open connection. ATP is described in the AppleTalk Manager chapters of Volume II
  9336. and Volume V.
  9337.  
  9338. ASP is designed to support a session between a server and one or more
  9339. workstations. It is an asymmetrical protocol: all exchanges are initiated by a
  9340. workstation and responded to by a server. The server cannot initiate an exchange
  9341. of data except to send to a workstation an attention message that directs the
  9342. workstation to request data from the server. An application running on a
  9343. workstation must make calls to ASP to communicate with any server that uses ASP.
  9344. If you want to develop a new type of asymmetrical, transaction-oriented server,
  9345. you should consider using ASP to implement it. ASP is described in the AppleTalk
  9346. Manager chapter of Volume V.
  9347.  
  9348. ADSP is a symmetrical protocol that you can use to establish and maintain a
  9349. connection between two equal entities (a peer-to-peer connection). Either end of
  9350. an ADSP connection can send data at any time. Although ADSP is a client of DDP
  9351. and therefore sends and receives data in packets (as do ATP and ASP), to an
  9352. application using ADSP the data appears to be sent and received as a continuous
  9353. stream. In addition to the duplex data stream maintained by an ADSP session,
  9354. ADSP allows either end of a connection to send an attention message to the other
  9355. end. You can use ADSP to establish two-way communication between computers, such
  9356. as an interoffice party line or a terminal emulation program. If you want to
  9357. develop an application that requires two-way communication, you should consider
  9358. using ADSP to implement it. ADSP is described in “Using ADSP” later in this
  9359. chapter.
  9360.  
  9361. _______________________________________________________________________________
  9362.  
  9363. æKY The….MPP…Driver…Volume…VI
  9364. æC »The .MPP Driver Volume VI                                            AppleTalk Manager
  9365. _______________________________________________________________________________
  9366.  
  9367. Within the AppleTalk Manager, the .MPP driver implements the LocalTalk Link
  9368. Access Protocol (LLAP), the Datagram Delivery Protocol (DDP), the Routing Table
  9369. Maintenance Protocol (RTMP) stub, the Name-Binding Protocol (NBP), and the
  9370. AppleTalk Echo Protocol (AEP). The AppleTalk Phase 2 version of the .MPP driver
  9371. includes a new function that returns information about the .MPP driver,
  9372. functions that send messages to routines in the AppleTalk Transition Queue, and
  9373. a new wildcard character for NBP.
  9374.  
  9375. _______________________________________________________________________________
  9376.  
  9377. æKY Getting…Information…About…the….MPP…Driver
  9378. æC »Getting Information About the .MPP Driver                            AppleTalk Manager
  9379. _______________________________________________________________________________
  9380.  
  9381. You can use the PGetAppleTalkInfo function to obtain information about the .MPP
  9382. driver. The PGetAppleTalkInfo function returns 
  9383.  
  9384.   •  a pointer to the .MPP global variables 
  9385.  
  9386.   •  a pointer to the .MPP driver’s device control entry (DCE) data structure
  9387.  
  9388.   •  configuration flags that indicate the status of certain conditions that are
  9389.   set at
  9390.       startup
  9391.  
  9392.   •  a value (the selfSend flag) that indicates whether the node can send
  9393.   packets to
  9394.       itself
  9395.  
  9396.   •  the range of network numbers for the network to which the node is attached
  9397.  
  9398.   •  the 8-bit node ID and 16-bit network number of the node
  9399.  
  9400.   •  the 8-bit node ID and 16-bit network number of the last router from which
  9401.   the 
  9402.        node has heard
  9403.  
  9404.   •  the maximum capacities of the .MPP driver, such as the maximum number of
  9405.       protocol handlers and the maximum number of static sockets allowed by this
  9406.       driver
  9407.  
  9408.   •  a pointer to the registered names queue
  9409.  
  9410.   •  the address of the node on the underlying data link (for example, the
  9411.   Ethernet
  9412.       hardware address)
  9413.  
  9414.   •  the node’s zone name
  9415.  
  9416. The data link address (for example, the Ethernet hardware address) and the zone
  9417. name are returned only for extended networks; that is, network types that allow
  9418. more than one network number per network. You must allocate memory for and
  9419. provide pointers to the data buffers into which the PGetAppleTalkInfo function
  9420. returns the data link address and zone name. You use the laLength parameter to
  9421. specify the length of the data link address you want returned; the function
  9422. returns the actual length of the data in the laLength parameter and returns the
  9423. data in the buffer you provide.
  9424.  
  9425.    Note:  Always use the PGetAppleTalkInfo function to obtain information about
  9426.    the .MPP driver. You can no longer rely on the validity of the global
  9427.    variables
  9428.    described in the AppleTalk Manager chapter of Volume II.
  9429.  
  9430. FUNCTION PGetAppleTalkInfo (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  9431.  
  9432. Parameter block
  9433.       ¨      16        ioResult             word          result code 
  9434.       Æ      26        csCode                word          always
  9435.       PGetAppleTalkInfo
  9436.       Æ      28        version              word          version of function
  9437.       ¨      30        varsPtr                long           pointer to .MPP
  9438.       globals
  9439.       ¨      34        dcePtr                  long           pointer to DCE for
  9440.       .MPP
  9441.       ¨      38        portID                 word          port number 
  9442.       ¨      40        configuration    long           configuration flags
  9443.       ¨      44        selfSend             word          nonzero if self-send
  9444.       is enabled
  9445.       ¨      46        netLo                  word          low value of the
  9446.       network range
  9447.       ¨      48        netHi                  word          high value of the
  9448.       network range
  9449.       ¨      50        ourAddr             long           local 24-bit AppleTalk
  9450.       address
  9451.       ¨      54        routerAddr        long           24-bit address of router
  9452.       ¨      58        numOfPHs        word          max number of protocol
  9453.       handlers
  9454.       ¨      60        numOfSkts        word          max number of static
  9455.       sockets
  9456.       ¨      62        numNBPEs       word          max concurrent NBP requests
  9457.       ¨      64        ntQueue              long          pointer to registered
  9458.       names queue
  9459.       ´      68        laLength             word          length in bytes of
  9460.       data link address
  9461.  
  9462.  
  9463.  
  9464.  
  9465.       Æ      70        linkAddr             long          pointer to data link
  9466.       address buffer
  9467.  
  9468.  
  9469.  
  9470.  
  9471.       Æ      74        zoneName          long          pointer to zone name
  9472.       buffer
  9473.  
  9474. The PGetAppleTalkInfo function returns information about the .MPP driver. If the
  9475. node on which your program is running happens also to be running AppleTalk
  9476. Internet Router software in the background, more than one set of .MPP global
  9477. variables may be in RAM. To make sure you are obtaining information about the
  9478. .MPP driver that handles application software, always use the PGetAppleTalkInfo
  9479. function rather than the Device Manager’s PBControl function. If you are using
  9480. assembly language or want to use the PBControl function, you must use a device
  9481. driver reference number of –10 for the .MPP driver.
  9482.  
  9483. Fields
  9484.  
  9485. ioResult                             The result of the function. When you
  9486. execute the function
  9487.                                              asynchronously, the function sets
  9488.                                              this parameter to 1 and
  9489.                                              returns a function result of noErr
  9490.                                              as soon as the function
  9491.                                              begins execution. When the function
  9492.                                              completes execution,
  9493.                                              it sets the ioResult parameter to
  9494.                                              the actual result code. 
  9495.  
  9496. csCode                                Routine selector, automatically set by the
  9497. MPW® interface.
  9498.                                             Always equal to PGetAppleTalkInfo
  9499.                                             for this function.
  9500.  
  9501. version                             The version number of the PGetAppleTalkInfo
  9502. function
  9503.                                             you are calling. For version number
  9504.                                             53 of the .MPP driver,
  9505.                                             this number is always 1.
  9506.  
  9507. varsPtr                              A pointer to the .MPP global variables.
  9508. This parameter is
  9509.                                             reserved for the use of Apple
  9510.                                             Computer, Inc.; you cannot
  9511.                                             rely on the validity of the
  9512.                                             variables pointed to by this
  9513.                                             parameter. 
  9514.  
  9515. dcePtr                                A pointer to the device control entry
  9516. (DCE) data structure
  9517.                                            for the .MPP driver. The DCE is
  9518.                                            described in the Device
  9519.                                            Manager chapters of Volumes II and V.
  9520.  
  9521. portID                               The port number for the .MPP driver. The
  9522. port number is
  9523.                                            always 0 unless you are requesting
  9524.                                            information for an .MPP
  9525.                                            driver being used by a router.
  9526.  
  9527. configuration                 A 32-bit long word of configuration flags. The
  9528. following
  9529.                                           flags are currently defined:
  9530.  
  9531.                                           Bit      Flag
  9532.                                           Description
  9533.                                           31       SrvAdrBit          TRUE (1)
  9534.                                           if the routine that opened
  9535.                                                                                
  9536.                                                                                
  9537.                                                                                
  9538.                                                                                
  9539.                                                                                
  9540.                                                                                
  9541.  
  9542.                                                                                
  9543.                                                                                
  9544.                                                                                
  9545.                                                                                
  9546.                                                                                
  9547.  
  9548.                                                                                
  9549.                                                                                
  9550.                                                                                
  9551.                                                                                
  9552.                                                                                
  9553.  
  9554.                                                                                
  9555.                                                                                
  9556.                                                                                
  9557.                                                                                
  9558.                                                                                
  9559.                                                                                
  9560.  
  9561.                                                                                
  9562.                                                                                
  9563.                                                                                
  9564.                                                                                
  9565.                                                                                
  9566.                                                                                
  9567.  
  9568.                                                                                
  9569.                                                                                
  9570.                                                                                
  9571.                                                                                
  9572.                                                                                
  9573.                                                                                
  9574.  
  9575.                                                                                
  9576.                                                                                
  9577.                                                                                
  9578.                                                                                
  9579.                                                                                
  9580.                                                                                
  9581.  
  9582.                                                                                
  9583.                                                                                
  9584.                                                                                
  9585.                                                                                
  9586.                                                                                
  9587.                                                                                
  9588.  
  9589.                                                                                
  9590.                                                                                
  9591.                                                                                
  9592.                                                                                
  9593.                                                                                
  9594.                                                                                
  9595.                                                                                
  9596.  
  9597.                                                                                
  9598.  
  9599.  
  9600.                                           30       RouterBit             TRUE
  9601.                                           (1) if an AppleTalk Internet
  9602.                                                                                
  9603.                                                                                
  9604.                                                                                
  9605.                                                                                
  9606.                                                                                
  9607.                                                                                
  9608.  
  9609.                                                                                
  9610.                                                                                
  9611.                                                                                
  9612.                                                                                
  9613.                                                                                
  9614.                                                                                
  9615.                                                                                
  9616.  
  9617.                                                                                
  9618.                                                                                
  9619.                                                                                
  9620.                                                                                
  9621.                                                                                
  9622.                                                                                
  9623.  
  9624.                                                                                
  9625.                                                                                
  9626.                                                                                
  9627.                                                                                
  9628.                                                                                
  9629.                                                                                
  9630.                                                                                
  9631.  
  9632.                                                                                
  9633.  
  9634.  
  9635.                                          15        ExtendedBit         TRUE (1)
  9636.                                          if the node is on an
  9637.                                                                                
  9638.                                                                                
  9639.                                                                                
  9640.                                                                                
  9641.                                                                                
  9642.                                                                                
  9643.  
  9644.                                                                                
  9645.                                                                                
  9646.                                                                                
  9647.                                                                                
  9648.                                                                                
  9649.                                                                                
  9650.  
  9651.                                                                                
  9652.                                                                                
  9653.                                                                                
  9654.                                                                                
  9655.                                                                                
  9656.                                                                                
  9657.  
  9658.  
  9659.                                            7       BadZoneHintBit   TRUE (1) if
  9660.                                            the zone name of the
  9661.                                                                                
  9662.                                                                                
  9663.                                                                                
  9664.                                                                                
  9665.                                                                                
  9666.                                                                                
  9667.                                                                                
  9668.                                                                                
  9669.                                                                                
  9670.  
  9671.                                                                                
  9672.                                                                                
  9673.                                                                                
  9674.                                                                                
  9675.                                                                                
  9676.                                                                                
  9677.  
  9678.                                                                                
  9679.                                                                                
  9680.                                                                                
  9681.                                                                                
  9682.                                                                                
  9683.                                                                                
  9684.  
  9685.                                                                                
  9686.                                                                                
  9687.                                                                                
  9688.                                                                                
  9689.                                                                                
  9690.                                                                                
  9691.  
  9692.                                                                                
  9693.                                                                                
  9694.                                                                                
  9695.                                                                                
  9696.                                                                                
  9697.                                                                                
  9698.                                                                                
  9699.  
  9700.                                                                                
  9701.                                                                                
  9702.                                                                                
  9703.                                                                                
  9704.                                                                                
  9705.                                                                                
  9706.  
  9707.                                                                                
  9708.                                                                                
  9709.                                                                                
  9710.                                                                                
  9711.                                                                                
  9712.                                                                                
  9713.  
  9714.                                                                                
  9715.                                                                                
  9716.                                                                                
  9717.                                                                                
  9718.                                                                                
  9719.                                                                                
  9720.  
  9721.                                                                                
  9722.                                                                                
  9723.                                                                                
  9724.                                                                                
  9725.  
  9726.                                                                                
  9727.  
  9728.  
  9729.                                            6       OneZoneBit           TRUE (1)
  9730.                                            if only one zone is
  9731.                                                                                
  9732.                                                                                
  9733.                                                                                
  9734.                                                                                
  9735.                                                                                
  9736.  
  9737.                                                                                
  9738.                                                                                
  9739.                                                                                
  9740.                                                                                
  9741.                                                                                
  9742.                                                                                
  9743.                                                                                
  9744.                                                                                
  9745.  
  9746.                                                                                
  9747.                                                                                
  9748.                                                                                
  9749.                                                                                
  9750.                                                                                
  9751.                                                                                
  9752.  
  9753.                                                                                
  9754.                                                                                
  9755.                                                                                
  9756.                                                                                
  9757.                                                                                
  9758.                                                                                
  9759.  
  9760.                                                                                
  9761.                                                                                
  9762.  
  9763.  
  9764. selfSend                           The ability of a node to send packets to
  9765. itself. This feature is
  9766.                                            enabled when this parameter is
  9767.                                            nonzero. Use the
  9768.                                            PSetSelfSend function, described in
  9769.                                            the AppleTalk Manager
  9770.                                            chapter of Volume V, to enable or
  9771.                                            disable this feature.
  9772.  
  9773. netLo                                 The low value of the range of network
  9774. numbers on the
  9775.                                             local cable. Only extended networks
  9776.                                             can have a range of
  9777.                                             network numbers. For a nonextended
  9778.                                             network, this
  9779.                                             parameter returns the network
  9780.                                             number.
  9781.  
  9782. netHi                                 The high value of the range of network
  9783. numbers on the
  9784.                                             local cable. Only extended networks
  9785.                                             can have a range of
  9786.                                             network numbers. For a nonextended
  9787.                                             network, this
  9788.                                             parameter returns the network
  9789.                                             number.
  9790.  
  9791. ourAddr                            The 24-bit AppleTalk network address of the
  9792. node you are
  9793.                                              on. The least significant byte of
  9794.                                              the long word is the node
  9795.                                              ID. The middle 16 bits are the
  9796.                                              network number. The most
  9797.                                              significant byte of the long word
  9798.                                              is reserved for use by
  9799.                                              Apple Computer, Inc. 
  9800.  
  9801. routerAddr                       The 24-bit AppleTalk network address of the
  9802. last router
  9803.                                              from which your node heard traffic.
  9804.                                              The least significant
  9805.                                              byte of the long word is the node
  9806.                                              ID. The middle 16 bits are
  9807.                                              the network number. The most
  9808.                                              significant byte of the long
  9809.                                              word is reserved for use by Apple
  9810.                                              Computer, Inc. You
  9811.                                              should always use this address when
  9812.                                              you want to
  9813.                                              communicate with a router.
  9814.  
  9815. numOfPHs                        The maximum number of protocol handlers that
  9816. this
  9817.                                              .MPP driver allows.
  9818.  
  9819. numOfSkts                        The maximum number of statically assigned
  9820. sockets that
  9821.                                               this .MPP driver allows.
  9822.                                               Statically assigned sockets are
  9823.                                               described in Inside AppleTalk.
  9824.  
  9825. numNBPEs                       The maximum number of concurrent requests to NBP
  9826. that
  9827.                                              this .MPP driver allows. 
  9828.  
  9829. ntQueue                             A pointer to the first entry in the names
  9830. table for the local
  9831.                                               node. You can use NBP routines to
  9832.                                               look up and register
  9833.                                               names in the names table. The
  9834.                                               names table is described in
  9835.                                              “Name-Binding Protocol” in the
  9836.                                              AppleTalk Manager
  9837.                                               chapter of Volume II.
  9838.  
  9839. laLength                            The number of bytes of the data link address
  9840. that the
  9841.                                              function should place in the buffer
  9842.                                              pointed to by the
  9843.                                              LinkAddr parameter. You use this
  9844.                                              parameter when you
  9845.                                              call the PGetAppleTalkInfo function
  9846.                                              on a node on an
  9847.                                              extended network. If you request
  9848.                                              more bytes than the total
  9849.                                              number of bytes in the address,
  9850.                                              then the function returns
  9851.                                              in the laLength parameter the
  9852.                                              actual number of bytes it
  9853.                                              placed in the buffer. If the
  9854.                                              address is longer than the size of
  9855.                                              the buffer, then the
  9856.                                              PGetAppleTalkInfo function fills
  9857.                                              the
  9858.                                              buffer and returns in the laLength
  9859.                                              parameter the actual
  9860.                                              length of the address, not the
  9861.                                              number of bytes returned. 
  9862.                                             The function does not return an
  9863.                                             error when the buffer is
  9864.                                              too large or too small for the
  9865.                                              address. A value of 6 bytes for
  9866.                                              laLength is sufficient for most
  9867.                                              purposes.
  9868.  
  9869. linkAddr                           A pointer to a buffer for the data link
  9870. address returned for
  9871.                                              extended networks only. You use the
  9872.                                              laLength parameter
  9873.                                              to specify the number of bytes of
  9874.                                              the address that you want
  9875.                                              placed in this buffer. You must
  9876.                                              allocate a buffer large
  9877.                                              enough to hold the number of bytes
  9878.                                              you specify. Specify
  9879.                                              NIL for this parameter if you do
  9880.                                              not want the function to
  9881.                                              provide a data link address.
  9882.  
  9883. zoneName                        A pointer to a buffer into which the
  9884. PGetAppleTalkInfo
  9885.                                              function places the local node’s
  9886.                                              zone name. You must
  9887.                                              allocate a buffer of at least 33
  9888.                                              bytes to hold this data, or you
  9889.                                             must specify NIL for the ZoneName
  9890.                                             parameter if you do
  9891.                                             not want to obtain the zone name.
  9892.                                             This field is returned
  9893.                                             only if the node is on an extended
  9894.                                             network.
  9895.    
  9896. Result codes
  9897.         noErr                     0           No error
  9898.         paramErr         –50            Version number is too high
  9899.  
  9900. _______________________________________________________________________________
  9901.  
  9902. æKY A…New…Nbp…Wildcard…Character
  9903. æC »A New Nbp Wildcard Character                                         AppleTalk Manager
  9904. _______________________________________________________________________________
  9905.  
  9906. The Name-Binding Protocol (NBP) allows the use of certain wildcard characters in
  9907. AppleTalk names when you call the PLookupName function. NBP now supports the
  9908. following wildcard characters:
  9909.  
  9910. NBP wildcard characters
  9911.  
  9912. =                                      All possible values. The equal sign (=)
  9913. can be used alone
  9914.                                          instead of a name in the object or type
  9915.                                          fields.
  9916.  
  9917. *                                      This zone. The asterisk (*) can be used
  9918. in place of the name of
  9919.                                         the zone to which this node belongs.
  9920.  
  9921. ≈                                      Any or no characters in this position.
  9922. The double tilde (≈) can
  9923.                                          be used to obtain matches for object or
  9924.                                          type fields. For
  9925.                                          example, pa≈l matches pal, paul, paper
  9926.                                          ball, and so forth. You
  9927.                                          can use only one double tilde in any
  9928.                                          string. Press Option-x to
  9929.                                         type the double tilde character on a
  9930.                                         Macintosh keyboard. If
  9931.                                         you use the double tilde alone, it has
  9932.                                         the same meaning as
  9933.                                         the equal sign (=). Note that any node
  9934.                                         not running AppleTalk
  9935.                                         Phase 2 drivers will not recognize this
  9936.                                         character.
  9937.  
  9938. _______________________________________________________________________________
  9939.  
  9940. æKY The…LAP…Manager…Volume…VI
  9941. æC »The LAP Manager Volume VI                                            AppleTalk Manager
  9942. _______________________________________________________________________________
  9943.  
  9944. The LAP Manager is a set of operating-system utilities that provide a standard
  9945. interface between the AppleTalk protocols and the various link access protocols,
  9946. such as LocalTalk (LLAP), EtherTalk (ELAP), and TokenTalk (TLAP). Because the
  9947. LAP Manager is running even when the .MPP driver is not open, the LAP Manager
  9948. also maintains the AppleTalk Transition Queue. In addition, the LAP Manager
  9949. contains protocol handlers for certain types of 802.2 packets. 
  9950.  
  9951. This section describes the AppleTalk Transition Queue and the LAP Manager 802.2
  9952. protocol handler, tells you how to add or remove an AppleTalk Transition Queue
  9953. entry, and describes how to attach or detach your own 802.2 protocol handler. In
  9954. addition to the LAP Manager features described here, you can use the LAP Manager
  9955. to interface new data links to AppleTalk. For more information about the LAP
  9956. Manager, see the AppleTalk Connections Programmer’s Guide . 
  9957.  
  9958. _______________________________________________________________________________
  9959.  
  9960. æKY The…Appletalk…Transition…Queue
  9961. æC »The Appletalk Transition Queue                                       AppleTalk Manager
  9962. _______________________________________________________________________________
  9963.  
  9964. At any given time there might be two or more applications running that use
  9965. AppleTalk. If one of these applications opens the AppleTalk drivers, the other
  9966. AppleTalk applications are affected. If the Operating System closes the
  9967. AppleTalk drivers, all AppleTalk applications are affected. To ensure that your
  9968. application is not adversely affected by such an event, your application can
  9969. place an entry in the AppleTalk Transition Queue. The LAP Manager sends a
  9970. message to each entry in the AppleTalk Transition Queue each time the Operating
  9971. System or any routine
  9972.  
  9973.   •  opens the .MPP driver
  9974.  
  9975.   •  closes the .MPP driver
  9976.  
  9977.   •  indicates that it intends to close the .MPP driver
  9978.  
  9979.   •  cancels its intention to close the .MPP driver
  9980.  
  9981.   •  defines its own AppleTalk event and calls the AppleTalk Transition Queue to
  9982.       inform it that such an event occurred
  9983.  
  9984. Each of these events is referred to as an AppleTalk transition.
  9985.  
  9986. Because the .MPP driver is not necessarily open when the AppleTalk Transition
  9987. Queue must be called, the LAP Manager maintains the queue. Each entry in the
  9988. AppleTalk Transition Queue is defined by the ATQentry data type.
  9989.  
  9990. TYPE ATQentry = 
  9991.      RECORD
  9992.         qLink:     ATQentryPtr;  {next queue entry}
  9993.         qType:     Integer;      {reserved}
  9994.         CallAddr:  ProcPtr       {pointer to your routine}
  9995.      END;
  9996.  
  9997. When you want to add an entry to the AppleTalk Transition Queue, you must create
  9998. an ATQentry data structure and give the LAP Manager a pointer to it. The qLink
  9999. field is a pointer to the next queue entry. You should set this field to NIL;
  10000. the LAP Manager fills it in when an application adds another entry to the queue.
  10001. The qType field is reserved to maintain consistency with other operating-system
  10002. queues. The CallAddr field is a pointer to a routine that you provide, as
  10003. described in “How the AppleTalk Manager Calls Your AppleTalk Transition Queue
  10004. Entry” later in this chapter.
  10005.  
  10006. Because you provide the memory for the AppleTalk Transition Queue entry, you can
  10007. add as many fields to the end of the entry as you wish for your own purposes.
  10008. Whenever your routine is called, the caller provides you with a pointer to the
  10009. queue entry so that you can have access to the information you stored at the end
  10010. of your queue entry.
  10011.  
  10012. There are four LAP Manager functions you can use that are related to the
  10013. AppleTalk Transition Queue:
  10014.  
  10015.   •  The LAPAddATQ function adds an entry to the AppleTalk Transition Queue.
  10016.       This function is described in the following section, “Adding and Removing
  10017.       AppleTalk Transition Queue Entries.”
  10018.  
  10019.   •  The LAPRmvATQ function removes an entry from the AppleTalk Transition
  10020.       Queue. This function is described in the following section, “Adding and
  10021.       Removing AppleTalk Transition Queue Entries.”
  10022.  
  10023.   •  The ATEvent procedure calls all the entries in the AppleTalk Transition
  10024.   Queue
  10025.       with an AppleTalk transition event of your own definition. This function
  10026.       is
  10027.       described in the section “Defining Your Own AppleTalk Transition,” later
  10028.       in
  10029.       this chapter.
  10030.  
  10031.   •  The ATPreFlightEvent function calls all the entries in the AppleTalk
  10032.       Transition Queue  with an AppleTalk transition event of your own
  10033.       definition
  10034.       and gives each entry the opportunity to respond. This function is
  10035.       described in
  10036.       the section “Defining Your Own AppleTalk Transition,” later in this
  10037.       chapter.
  10038.  
  10039. _______________________________________________________________________________
  10040.  
  10041. æKY Adding…and…Removing…Appletalk…Transition…Queue…Entries
  10042. æC »Adding and Removing Appletalk Transition Queue Entries               AppleTalk Manager
  10043. _______________________________________________________________________________
  10044.  
  10045. You can use LAP Manager routines to add or remove an entry to the AppleTalk
  10046. Transition Queue.
  10047.  
  10048.           _____________________________________________________
  10049.            Assembly-language note:  From assembly language, you add and 
  10050.            remove AppleTalk Transition Queue entries by placing a routine 
  10051.            selector in the D0 register, placing a pointer to your AppleTalk 
  10052.            Transition Queue entry in the A0 register, and executing a JSR 
  10053.            instruction to an offset past the start of the LAP Manager. The start
  10054.  
  10055.            of the LAP Manager is contained in the global variable LAPMgrPtr 
  10056.            ($B18). The offset to the LAP Manager routines is given by the 
  10057.            constant LAPMgrCall (2).
  10058.          
  10059.            Here is assembly-language code that adds or removes AppleTalk 
  10060.            Tranisition Queue entries:
  10061.  
  10062.            LAPMgrPtr        EQU     $B18          ;entry point for LAP Manager
  10063.       LAPMgrCall       EQU     2             ;offset to LAP Manager routines
  10064.       ATQEntry         EQU     *             ;pointer to ATQ entry
  10065.       ...    
  10066.  
  10067.                        MOVEQ   #RSel,D0      ;place routine selector 
  10068.                                              ; in D0 (23 to add an entry, 24
  10069.                                              ; to remove one)
  10070.                       MOVE.L  LAPMgrPtr,An   ;put pointer to LAP Mgr in An
  10071.                       MOVE.L  ATQEntry,A0    ;put ATQ entry in A0 
  10072.                       JSR     LAPMgrCall(An) ;jump to start of LAP Mgr
  10073.                                              ; routines
  10074.           _____________________________________________________
  10075.  
  10076. FUNCTION LAPAddATQ (theATQEntry: ATQEntryPtr): OSErr;
  10077.  
  10078.           __________________________________________________
  10079.            On entry                    D0: 23
  10080.                                                A0: pointer to AppleTalk
  10081.                                                Transition Queue entry
  10082.            On exit                       D0: result code
  10083.           __________________________________________________
  10084.  
  10085. The LAPAddATQ function adds an entry to the AppleTalk Transition Queue. The
  10086. parameter theATQEntry is a pointer to an ATQentry data structure. The CallAddr
  10087. field of the data structure holds a pointer to the routine that AppleTalk calls
  10088. for any AppleTalk transition event. The ATQentry data structure is described in
  10089. the preceding section, “The AppleTalk Transition Queue.”
  10090.  
  10091.    Result codes
  10092.           noErr           0         No error
  10093.  
  10094. FUNCTION LAPRmvATQ (theATQEntry: ATQEntryPtr): OSErr;
  10095.  
  10096.           _________________________________________________
  10097.  
  10098.            On entry                  D0: 24
  10099.                                              A0: pointer to AppleTalk Transition
  10100.                                              Queue entry
  10101.            On exit                     D0: result code
  10102.           _________________________________________________
  10103.  
  10104. The LAPRmvATQ function removes an entry from the AppleTalk Transition Queue. The
  10105. parameter theATQEntry is a pointer to an ATQentry data structure. 
  10106.  
  10107.    Note:  You must not call the LAPRmvATQ function at interrupt time or through
  10108.    a callback routine. This restriction is to prevent any routine from removing
  10109.    an
  10110.    entry from the AppleTalk Transition Queue while another routine is in the
  10111.    process of adding or removing an entry.
  10112.  
  10113.    Result codes
  10114.           noErr           0           No error
  10115.           qErr            –1           Queue element not found
  10116. _______________________________________________________________________________
  10117.  
  10118. æKY Sending…Messages…to…the…Appletalk…Transition…Queue
  10119. æC »Sending Messages to the Appletalk Transition Queue                   AppleTalk Manager
  10120. _______________________________________________________________________________
  10121.  
  10122. Whereas it is unlikely that opening the .MPP driver will adversely affect
  10123. another program, an application should never close the .MPP driver, because
  10124. another program might be using it. Under certain circumstances, however, the
  10125. system might close the .MPP driver. The system uses the .MPP driver’s
  10126. PATalkClosePrep function to send a permission-to-close transition to each
  10127. routine in the AppleTalk Transition Queue. This transition indicates that the
  10128. system intends to close the .MPP driver so that each routine in the queue has
  10129. the opportunity to deny permission to do so.
  10130.  
  10131. When the system calls the PATalkClosePrep function, any routine in the AppleTalk
  10132. Transition Queue that wishes to deny permission to close the .MPP driver may
  10133. return a pointer to a Pascal string. The Pascal string should be the name of the
  10134. application that placed the entry in the queue. If any routine in the AppleTalk
  10135. Transition Queue denies permission to close the .MPP driver, the PATalkClosePrep
  10136. function returns the result code closeErr.
  10137.  
  10138. If any routine denies permission to close the .MPP driver, the AppleTalk Manager
  10139. sends a cancel-close transition to every routine in the AppleTalk Transition
  10140. Queue that previously received the permission-to-close transition. The caller of
  10141. the PATalkClosePrep function may display a dialog box informing the user that
  10142. another application is using the .MPP driver and showing the name (if any)
  10143. returned by the AppleTalk Transition Queue routine. The dialog box gives the
  10144. user the option of canceling the request to close AppleTalk or of closing
  10145. AppleTalk anyway. 
  10146.  
  10147. If the user chooses to close AppleTalk despite the fact that an application is
  10148. using it, the system calls the MPPClose function. AppleTalk then calls each
  10149. application in the AppleTalk Transition Queue, this time informing each one that
  10150. AppleTalk is about to close. In this case, your AppleTalk Transition Queue
  10151. routine must prepare for the imminent closing of AppleTalk; it cannot deny
  10152. permission to the MPPClose function. 
  10153.  
  10154. FUNCTION PATalkClosePrep (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  10155.  
  10156.    Parameter block
  10157.         Æ     26      csCode              word      always PATalkClosePrep
  10158.         ¨     28      appName        long        pointer to name of application 
  10159.                                                                      that
  10160.                                                                      denies
  10161.                                                                      request
  10162.  
  10163. The PATalkClosePrep function calls each routine listed in the AppleTalk
  10164. Transition Queue to request permission to close the .MPP driver. 
  10165.  
  10166. If a routine in the AppleTalk Transition Queue denies permission to close the
  10167. .MPP driver, that routine can return a pointer to a Pascal string. The Pascal
  10168. string should contain the name of the application that placed the entry in the
  10169. AppleTalk Transition Queue. The PATalkClosePrep function returns that pointer in
  10170. the appName field. The function also returns the result code closeErr,
  10171. indicating that the calling routine has been denied permission to close the .MPP
  10172. driver. The routine that called PATalkClosePrep can then display a dialog box
  10173. telling the user the name of the application that is currently using AppleTalk
  10174. and asking whether to close AppleTalk anyway. 
  10175.  
  10176. The csCode parameter is a routine selector; it is always equal to
  10177. PATalkClosePrep for this function.
  10178.  
  10179.    Result codes
  10180.           noErr                0         No error
  10181.           closeErr        –24         Permission to close .MPP driver was denied
  10182.  
  10183. _______________________________________________________________________________
  10184.  
  10185. æKY How…the…Appletalk…Manager…Calls…Your…Queue…Entry
  10186. æC »How the Appletalk Manager Calls Your Queue Entry                     AppleTalk Manager
  10187. _______________________________________________________________________________
  10188.  
  10189. When you have used the LAPAddATQ function to add an entry to the AppleTalk
  10190. Transition Queue, the AppleTalk Manager calls your entry when any of the
  10191. following events occurs:
  10192.  
  10193.   •  A routine opens the .MPP driver. 
  10194.  
  10195.   •  A routine closes the .MPP driver. 
  10196.  
  10197.   •  A routine calls the PATalkClosePrep function. 
  10198.  
  10199.   •  One of the routines in the AppleTalk Transition Queue denies permission for
  10200.       the routine that called the PATalkClosePrep function to close AppleTalk.
  10201.  
  10202.   •  An application calls the ATEvent or ATPreFlightEvent routines to send its
  10203.   own
  10204.       AppleTalk transition event to the entries in the AppleTalk Transition
  10205.       Queue.
  10206.  
  10207. When the AppleTalk Manager calls your AppleTalk Transition Queue routine, the
  10208. stack looks like this:
  10209.  
  10210. Chart 32-1 Contents of the stack on a call to an ATQ routine ø 
  10211.  
  10212. The first item on the stack (after the return address) is a routine selector.
  10213. There is one routine selector for each type of transition. The open,
  10214. prepare-to-close, permission-to-close, and cancel-close transitions each have a
  10215. single-digit routine selector; all other routine selectors for AppleTalk
  10216. transition events are 4-character codes. Codes starting with an uppercase letter
  10217. (A through Z) are reserved for use by developers. All other codes are reserved
  10218. for use by Apple Computer, Inc.
  10219.  
  10220.    Routine selector                                Transition
  10221.  
  10222.     $00 00 00 00                                         .MPP driver opened
  10223.     $00 00 00 02                                         .MPP driver about to
  10224.     close
  10225.     $00 00 00 03                                         PATalkClosePrep
  10226.     function has been called
  10227.     $00 00 00 04                                         Closing of .MPP driver
  10228.     has been canceled
  10229.     $41 xx xx xx —$5A xx xx xx             Reserved for use by developers
  10230.     all others                                            Reserved for use by
  10231.     Apple Computer
  10232.  
  10233. You can use the following constants for the standard AppleTalk transitions:
  10234.  
  10235. CONST  ATTransOpen        = 0;                {open transition}
  10236.        ATTransClose       = 2;                {prepare-to-close transition}
  10237.        ATTransClosePrep   = 3;                {permission-to-close 
  10238.                                                transition}
  10239.        ATTransCancelClose = 4;                {cancel-close transition} 
  10240.  
  10241. The second item passed to your routine on the stack is a pointer to your
  10242. routine’s entry in the AppleTalk Transition Queue. You can use this pointer to
  10243. get access to any fields at the end of the queue entry that you allocated for
  10244. your own use. The last item passed to your routine on the stack is a parameter
  10245. whose meaning depends on the type of transition. 
  10246.  
  10247. The interface between the AppleTalk Transition Queue and your routine follows
  10248. these conventions: Your routine must preserve all registers except D0, D1, D2,
  10249. A0, and A1; all parameters are passed on the stack as long words. Because your
  10250. routine might be called at interrupt time, your routine must not make any direct
  10251. or indirect calls to the Memory Manager and can’t depend on handles to unlocked
  10252. blocks being valid. If you want to use any of your application’s global
  10253. variables, you must save the contents of the A5 register before using the
  10254. variables, and you must restore the A5 register before your routine terminates.
  10255. These restrictions do not apply to the open transition or the prepare-to-close
  10256. transition.
  10257.  
  10258.    Note:  It is important that you return a 0 in the D0 register whenever you
  10259.    receive
  10260.    a transition event routine selector that you do not recognize or do not
  10261.    choose to
  10262.    handle. Returning a nonzero value in the D0 register might cause the system
  10263.    to
  10264.    cancel an attempt to close AppleTalk, for example, or might be misinterpreted
  10265.    in
  10266.    some other way. 
  10267.  
  10268.  
  10269. Open Transition 
  10270.  
  10271. When an application calls the MPPOpen function, the AppleTalk Manager first
  10272. attempts to open the .MPP driver. If the .MPP driver is already open, the
  10273. AppleTalk Manager does not call the AppleTalk Transition Queue. If the AppleTalk
  10274. Manager successfully opens the .MPP driver, it then calls every routine listed
  10275. in the AppleTalk Transition Queue with an open transition.
  10276.  
  10277. The third item on the stack for an open transition is a pointer to the start of
  10278. the Device Manager extended parameter block used by the routine that opened the
  10279. .MPP driver. This pointer is provided for your information only; you must not
  10280. change any of the fields in this parameter block. 
  10281.  
  10282. Your AppleTalk Transition Queue routine can perform any tasks you wish in
  10283. response to the notification that the .MPP driver has been opened, such as using
  10284. the Name-Binding Protocol (NBP) to register a name on the internet. Return 0 in
  10285. the D0 register to indicate that your routine executed with no error.
  10286.  
  10287.  
  10288. Prepare-to-Close Transistion
  10289.  
  10290. When any routine calls the MPPClose function to close the .MPP driver, the
  10291. AppleTalk Manager calls every routine listed in the AppleTalk Transition Queue
  10292. before the .MPP driver closes. If the .MPP driver is already closed when a
  10293. routine calls the MPPClose function, the AppleTalk Manager does not call the
  10294. routines in the AppleTalk Transition Queue.
  10295.  
  10296. When the AppleTalk Manager calls your routine for a prepare-to-close transition,
  10297. the third item on the stack is a NIL pointer.
  10298.  
  10299. Your routine can perform any tasks you wish to prepare for the imminent closing
  10300. of AppleTalk, such as ending a session with a remote terminal and informing the
  10301. user that the connection is being closed. You must return control to the
  10302. AppleTalk Manager as quickly as possible. Return 0 in the D0 register to
  10303. indicate that your routine executed with no error.
  10304.  
  10305.    Note:  When the AppleTalk Manager calls your routine with a prepare-to-close
  10306.    transition (that is, a routine selector of ATTransClose), you cannot prevent
  10307.    the
  10308.    .MPP driver from closing.
  10309.  
  10310.  
  10311. Permission-to-Close Transition 
  10312.  
  10313. When a routine calls the PATalkClosePrep function to inform the AppleTalk
  10314. Manager that it wants to close the .MPP driver, the AppleTalk Manager calls
  10315. every routine listed in the AppleTalk Transition Queue to request permission to
  10316. close the .MPP driver. 
  10317.  
  10318. When the AppleTalk Manager calls your routine to request permission to close the
  10319. .MPP driver, the third parameter on the stack is a pointer to a 4-byte buffer.
  10320. If you intend to deny the request to close AppleTalk, you should place in the
  10321. buffer a pointer to a Pascal string containing the name of your application. The
  10322. PATalkClosePrep function returns this pointer. The routine that called the
  10323. PATalkClosePrep function can then display a dialog box telling the user the name
  10324. of the application that is currently using AppleTalk.
  10325.  
  10326. Your routine can return either a function result of 0 in the D0 register,
  10327. indicating that it accepts the request to close, or a 1 in the D0 register,
  10328. indicating that it denies the request to close. Note that the Operating System
  10329. might elect to close AppleTalk anyway; for example, if the user grants
  10330. permission to close in response to a dialog box.
  10331.  
  10332. Because the AppleTalk Manager calls your routine again (with the routine
  10333. selector set to ATTransClose) before the .MPP driver actually closes, it is not
  10334. necessary for your routine to do anything other than grant or deny permission in
  10335. response to being called for a permission-to-close transition. However, you
  10336. might want to prohibit the users from opening new sessions or establishing new
  10337. connections while you are waiting for the .MPP driver to close.
  10338.  
  10339.  
  10340. Cancel-Close Transition 
  10341.  
  10342. When any routine in the AppleTalk Transition Queue denies permission for the
  10343. .MPP driver to close, the AppleTalk Manager calls each routine listed in the
  10344. AppleTalk Transition Queue that has already received the permission-to-close
  10345. transition to inform it that the request to close the .MPP driver has been
  10346. canceled. 
  10347.  
  10348. When the AppleTalk Manager calls your AppleTalk Transition Queue routine for a
  10349. cancel-close transition, the third item on the stack is a NIL pointer.
  10350.  
  10351. If your routine performed any tasks to prepare for the closing of AppleTalk, it
  10352. should reverse their effects when it is called with the routine selector set to
  10353. ATTransCancelClose. Return 0 in the D0 register to indicate that your routine
  10354. executed with no error.
  10355.  
  10356.  
  10357. Developer-Defined Transitions 
  10358.  
  10359. Any AppleTalk transition event code that begins with an uppercase letter (that
  10360. is, any value in the range $41 00 00 00  through $5A FF FF FF) indicates a
  10361. developer-defined event. You can use such events to send messages to your own
  10362. entries in the AppleTalk Transition Queue, or you can define events and make
  10363. them public for others to use. Because you cannot tell how the originator of
  10364. such an event might interpret a nonzero function result, you must always return
  10365. 0 in the D0 register for any AppleTalk transition event code that you do not
  10366. recognize.
  10367.  
  10368. When you return a nonzero result code for certain developer-defined transitions,
  10369. the AppleTalk Manager may call your AppleTalk Transition Queue routine a second
  10370. time with a cancel transition analogous to the cancel-close transition. 
  10371.  
  10372.  
  10373. _______________________________________________________________________________
  10374.  
  10375. æKY Defining…Your…Own…Appletalk…Transition
  10376. æC »Defining Your Own Appletalk Transition                               AppleTalk Manager
  10377. _______________________________________________________________________________
  10378.  
  10379. You can define your own AppleTalk transition to have any meaning you choose. For
  10380. example, you might want to call every routine in the AppleTalk Transition Queue
  10381. each time you open an AppleTalk Data Stream Protocol (ADSP) connection.
  10382.  
  10383. You can use either the ATEvent procedure or the ATPreFlightEvent function to
  10384. notify all of the routines in the AppleTalk Transition Queue that your AppleTalk
  10385. transition has occurred. Whereas the ATEvent procedure only calls the routines
  10386. in the queue with a transition event, the ATPreFlightEvent function also allows
  10387. each routine in the AppleTalk Transition Queue to return a result code and other
  10388. information to your calling routine.
  10389.  
  10390.    Note:  You can call the ATEvent and ATPreFlightEvent routines only at
  10391.    virtual-memory safe time. See the Memory Manager chapter in this volume for
  10392.    information on virtual memory. 
  10393.  
  10394. PROCEDURE ATEvent (event: LongInt; infoPtr: Ptr);
  10395.  
  10396. The ATEvent procedure calls all of the routines in the AppleTalk Transition
  10397. Queue with the AppleTalk transition event code you specify in the event
  10398. parameter. The AppleTalk transition event code can be any 4-character string
  10399. that starts with an uppercase letter; that is, any value in the range $41 00 00
  10400. 00  through $5A FF FF FF. You can use the infoPtr parameter to point to any
  10401. information that you want to make available to the AppleTalk Transition Queue
  10402. routines; for an ADSP-open transition, for example, you might pass a pointer to
  10403. the parameter block used by the dspOpen routine. If you do not want to pass any
  10404. information to the AppleTalk Transition Queue routines, set the infoPtr
  10405. parameter to NIL.
  10406.  
  10407. FUNCTION ATPreFlightEvent (event,cancel: LongInt; infoPtr: Ptr) : OSErr; 
  10408.  
  10409. The ATPreFlightEvent function calls all of the routines in the AppleTalk
  10410. Transition Queue with the AppleTalk transition event code you specify in the
  10411. event parameter. If any routine in the AppleTalk Transition Queue returns a
  10412. nonzero function result, the ATPreFlightEvent function calls each of the
  10413. routines that it has already called, this time with the AppleTalk transition
  10414. event code you specify in the cancel parameter. The AppleTalk transition event
  10415. codes can be any 4-character strings that start with an uppercase letter; that
  10416. is, any values in the range $41 00 00 00  through $5A FF FF FF. You can use the
  10417. infoPtr parameter to point to any information that you want to make available to
  10418. the AppleTalk Transition Queue routines. If you do not want to pass any
  10419. information to the AppleTalk Transition Queue routines, set the infoPtr
  10420. parameter to NIL.
  10421.  
  10422.    Result codes
  10423.           noErr          0         No error, or unrecognized event code
  10424.  
  10425.    Note:  AppleTalk transitions defined by developers might return other result
  10426.    codes.
  10427.  
  10428.  
  10429. _______________________________________________________________________________
  10430.  
  10431. æKY The…LAP…Manager…802.2…Protocol
  10432. æC »The LAP Manager 802.2 Protocol                                       AppleTalk Manager
  10433. _______________________________________________________________________________
  10434.  
  10435. The Institute of Electrical and Electronics Engineers (IEEE) has defined a
  10436. series of communications protocols for use on a variety of networks. At the
  10437. physical level, these protocols include the 802.3 CSMA/CD protocol, the 802.4
  10438. token bus protocol, and the 802.5 token ring protocol. At the data link level,
  10439. you access these protocols through another IEEE protocol, the 802.2 protocol.
  10440. The AppleTalk LAP Manager includes two routines that allow you to attach and
  10441. detach protocol handlers for 802.2 Type 1 data packets: the L802Attach and
  10442. L802Detach routines. You can write an application that reads 802.2 Type 1 data
  10443. packets and use the L802Attach routine to install your application as a client
  10444. of the LAP Manager. The ANSI/IEEE standards for the 802 protocols are published
  10445. by the IEEE.
  10446.  
  10447. The first 14 bytes of a packet sent or received by the .ENET driver constitute
  10448. the header. The first 12 bytes consist of the destination and source data-link
  10449. addresses, such as the Ethernet hardware addresses. If the value of the last 2
  10450. bytes in the header is greater than 1500, then the .ENET driver treats that
  10451. field as an Ethernet protocol type discriminator. See “The .ENET Driver,” later
  10452. in this chapter, for more information on Ethernet protocols. If the value of the
  10453. last 2 bytes in the header is less than or equal to 1500, then the packet is an
  10454. 802.3 protocol packet and this field indicates the length of the 802.3 data. The
  10455. .ENET driver passes all 802.3 packets to the LAP Manager.
  10456.  
  10457. The LAP Manager receives the entire 802.3 packet from the .ENET driver. The
  10458. first 3 bytes of the 802.3 data constitute the header for the 802.2 protocol.
  10459. The first byte of the 802.2 header is known as the destination service access
  10460. point (DSAP). If the DSAP field is equal to $AA, then the first 5 bytes of the
  10461. 802.2 data constitute a protocol discriminator known as the subnetwork access
  10462. protocol (SNAP) type. If the SNAP type field is $00000080F3, indicating the
  10463. AppleTalk Address Resolution Protocol (AARP), then the next 4 bytes of the 802.2
  10464. data constitute a third type field, the AARP packet type. AARP is discussed in
  10465. Inside AppleTalk.
  10466.  
  10467. The first packet header in Figure 32-4, for example, indicates an Ethernet
  10468. packet containing AppleTalk Phase 1 data. The .ENET driver would deliver this
  10469. packet to the AppleTalk Phase 1 protocol handler.
  10470.  
  10471. By contrast, the second data packet header in the figure indicates an 802.3
  10472. packet containing AppleTalk Phase 2 data. The .ENET driver would deliver this
  10473. packet to the AppleTalk Phase 2 LAP Manager. 
  10474.  
  10475. Similarly, the third data packet header in Figure 32-4 indicates an 802.3 packet
  10476. to be delivered to the Phase 2 EtherTalk AARP handler:
  10477.  
  10478. ¿ Figure 32-4   AppleTalk Ethernet packet formats ø 
  10479.  
  10480. When you call the L802Attach routine, you provide a pointer to your protocol
  10481. handler, the reference number of the .ENET driver, and a pointer to a string
  10482. containing one or more type fields. The type fields indicate the DSAP value and
  10483. any other protocol type fields (such as the SNAP type and the AARP type). The
  10484. LAP Manager delivers to your protocol handler any 802.2 data packets that have
  10485. the protocol type you specify. 
  10486.  
  10487. _______________________________________________________________________________
  10488.  
  10489. æKY Attaching…and…Detaching…802.2…Protocol…Handlers
  10490. æC »Attaching and Detaching 802.2 Protocol Handlers                      AppleTalk Manager
  10491. _______________________________________________________________________________
  10492.  
  10493. You can attach to the LAP Manager your own protocol handler for 802.2 protocols.
  10494. The LAP Manager has permanent handlers for certain types of EtherTalk packets.
  10495. You cannot replace or override the permanent LAP Manager protocol handlers. 
  10496.  
  10497. There are no high-level interfaces for the LAP Manager 802.2 protocol routines.
  10498. You call these routines from assembly language by placing a routine selector in
  10499. the D0 register and executing a JSR instruction to an offset 2 bytes past the
  10500. start of the LAP Manager. The start of the LAP Manager is contained in the
  10501. global variable LAPMgrPtr ($B18). 
  10502.  
  10503. Before you call these routines, you must place the reference number of the .ENET
  10504. driver in the D2 register and a pointer to the protocol type specification in
  10505. the A1 register. Before you call the L802Attach routine, you must also place a
  10506. pointer to your protocol handler in the A0 register. Both routines return a
  10507. nonzero value in the D0 register if there is an error. 
  10508.  
  10509. Listing 32-1 shows how to call a LAP Manager L802.2 routine from assembly
  10510. language.
  10511.  
  10512. ¿ Listing 32-1   Calling a LAP Manager L802.2 routine from assembly language
  10513.  
  10514. LAPMgrPtr   EQU     $B18            ;entry point for LAP Manager
  10515. LAPMgrCall  EQU     2               ;offset to LAP Manager routines
  10516. L802Entry   EQU     *               ;L802 routine entry
  10517. ...
  10518.  
  10519.             MOVEQ   #RSel,D0        ;place routine selector 
  10520.                                     ; in D0
  10521.             MOVEQ   #refNum,D2      ;place driver reference number
  10522.                                     ; in D2
  10523.             MOVE.L  PHndlrPtr,A0    ;put pointer to protocol 
  10524.                                     ; handler in A0 (L802Attach 
  10525.                                     ; only)
  10526.             MOVE.L  PSpecPtr,A1     ;put pointer to protocol 
  10527.                                     ; specification in A1)
  10528.             MOVE.L  LAPMgrPtr,An    ;put pointer to LAP Mgr in An
  10529.             JSR     LAPMgrCall(An)  ;jump to start of LAP Mgr
  10530.                     ; routines
  10531.  
  10532.  
  10533. L802Attach
  10534.           _______________________________________________
  10535.            On entry                   D0: 21
  10536.                                               D2: reference number of .ENET
  10537.                                               driver
  10538.                                               A0: pointer to your protocol
  10539.                                               handler
  10540.                                               A1: pointer to protocol
  10541.                                               specification
  10542.  
  10543.            On exit                     D0: nonzero if error 
  10544.           _______________________________________________
  10545.  
  10546. The L802Attach routine attaches to the LAP Manager a protocol handler for a
  10547. specific IEEE 802.2 protocol type.
  10548.  
  10549. Before calling this routine, you must put the value 21 in the D0 register and
  10550. the reference number of the .ENET driver in the D2 register. The .ENET driver
  10551. reference number is returned by the OpenSlot function. If you are not using the
  10552. .ENET driver or a driver that uses the same interface as the .ENET driver, you
  10553. cannot use the L802Attach routine. 
  10554.  
  10555. You must put a pointer to your protocol handler in the A0 register and a pointer
  10556. to the protocol-type specification for this protocol handler in the A1 register.
  10557. The protocol-type specification consists of one or more protocol-type fields,
  10558. each preceded by a length byte. The LAP Manager reads the protocol-type fields
  10559. in the 802.2 data packet header to determine to which protocol handler (if any)
  10560. to deliver the packet. The first type field in your protocol specification is
  10561. the 1-byte DSAP. If the DSAP type field is equal to $AA, then the protocol-type
  10562. specification must contain a second type field, the 5-byte SNAP type. If the
  10563. SNAP type field is $00000080F3, indicating the AppleTalk Address Resolution
  10564. Protocol (AARP), then the protocol-type specification must contain a third type
  10565. field, the 4byte AARP protocol type. Terminate the list of protocol-type fields
  10566. with a byte of zeros.
  10567.  
  10568. The following protocol-type specification, for example, is for the permanent LAP
  10569. Manager protocol handler for an 802.3 packet containing AppleTalk data. The
  10570. .ENET driver would deliver this packet to the AppleTalk Phase 2 LAP Manager. The
  10571. first byte, $01, is the length byte for the first protocol-type field (the DSAP
  10572. type field), $AA. The third byte, $05, is the length byte for the next
  10573. protocol-type field, the SNAP. The final byte ($00) terminates the type
  10574. specification.
  10575.  
  10576. 01 AA 05 08 00 07 80 9B 00
  10577.  
  10578. The following protocol-type specification is for the permanent LAP Manager
  10579. protocol handler for an 802.3 packet to be delivered to the EtherTalk AARP
  10580. handler. Notice that the SNAP field is followed by an additional type field, the
  10581. AARP protocol type.
  10582.  
  10583. 01 AA 05 00 00 00 80 F3 04 00 01 80 9B 00
  10584.  
  10585.    Note:  The DSAP value of $AA is reserved for use with protocol-type
  10586.    specifications that include a SNAP field. The SNAP value of $08 00 07 80 9B
  10587.    is
  10588.    reserved for AppleTalk data. The SNAP value of $00 00 00 80 F3 is reserved
  10589.    for
  10590.    AARP data. The AARP protocol type value of $00 01 80 9B is reserved for
  10591.    EtherTalk AARP packets.  
  10592.  
  10593. See the ANSI/IEEE standard 802.2 for more information about 802.2 protocols, and
  10594. see Inside AppleTalk for more information about AARP.
  10595.  
  10596.  
  10597. L802Detach
  10598.           ________________________________________________
  10599.            On entry                     D0: 22
  10600.                                                 D2: reference number of .ENET
  10601.                                                 driver
  10602.                                                 A1: pointer to protocol
  10603.                                                 specification
  10604.  
  10605.            On exit                        D0: nonzero if error 
  10606.           ________________________________________________
  10607.  
  10608. The L802Detach routine detaches from the LAP Manager a protocol handler for a
  10609. specific IEEE 802.2 protocol type.
  10610.  
  10611. Before calling this routine, you must put the value 22 in the D0 register and
  10612. the reference number of the .ENET driver in the D2 register. The .ENET driver
  10613. reference number is returned by the OpenSlot function. If you are not using the
  10614. .ENET driver or a driver that uses the same interface as the .ENET driver, you
  10615. cannot use the L802Detach routine. 
  10616.  
  10617. You must put a pointer to the protocol-type specification for this protocol
  10618. handler in the A1 register. You must specify exactly the same protocol type as
  10619. you specified for the L802Attach routine when you attached the protocol handler.
  10620.  
  10621. _______________________________________________________________________________
  10622.  
  10623. æKY The….ATP…Driver…Volume…VI
  10624. æC »The .ATP Driver Volume VI                                            AppleTalk Manager
  10625. _______________________________________________________________________________
  10626.  
  10627. AppleTalk Phase 2 includes two changes to the .ATP driver: you can now cancel
  10628. all calls to the ATPGetRequest function that are pending execution, and you can
  10629. now set the release timer for AppleTalk Transaction Protocol (ATP) exactly-once
  10630. (XO) service to one of five different values. 
  10631.  
  10632. _______________________________________________________________________________
  10633.  
  10634. æKY Canceling…All…Calls…to…the…Atpgetrequest…Function
  10635. æC »Canceling All Calls to the Atpgetrequest Function                    AppleTalk Manager
  10636. _______________________________________________________________________________
  10637.  
  10638. The ATPGetRequest function sets a socket to receive a request sent by another
  10639. socket. If you call the ATPGetRequest function asynchronously, you can have
  10640. several calls to the function simultaneously pending execution. The
  10641. ATPKillAllGetReq function cancels all calls to the ATPGetRequest function
  10642. pending for a specific socket without closing the socket. 
  10643.  
  10644. FUNCTION ATPKillAllGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  10645.  
  10646.    Parameter block
  10647.         Æ     26      csCode            word     always ATPKillAllGetReq
  10648.         Æ     28      atpSocket        byte      socket for which to cancel all
  10649.         calls 
  10650.                                                                  to
  10651.                                                                  ATPGetRequest
  10652.  
  10653. The ATPKillAllGetReq function cancels all pending asynchronous calls to the
  10654. ATPGetRequest function for the socket you specify with the atpSocket parameter.
  10655. The ATPKillAllGetReq function also calls the completion routine for each call to
  10656. the ATPGetRequest function with the result code reqAborted (–1105) in the D0
  10657. register. 
  10658.  
  10659. Unlike the ATPCloseSocket function, the ATPKillAllGetReq function does not close
  10660. the socket. You should call the ATPKillAllGetReq function before closing a
  10661. socket. The csCode parameter is a routine selector, automatically set by the MPW
  10662. interface. It is always equal to ATPKillAllGetReq for this function.
  10663.  
  10664.    Result codes
  10665.         noErr                         0    No error
  10666.         cbNotFound    –1102    Control block not found; no pending asynchronous
  10667.         calls
  10668. _______________________________________________________________________________
  10669.  
  10670. æKY Setting…the…Timeout…Value…for…the…Atp…Release…Timer
  10671. æC »Setting the Timeout Value for the Atp Release Timer                  AppleTalk Manager
  10672. _______________________________________________________________________________
  10673.  
  10674. The .ATP driver maintains a timer, called the release timer , for each call to
  10675. the PSendResponse function that is part of an exactly-once (XO) transaction. If
  10676. the timer expires before the transaction is complete (that is, before the socket
  10677. receives the transaction release packet), the driver completes the PSendResponse
  10678. function. Before AppleTalk Phase 2, the release timer was always set to 30
  10679. seconds. To set the other connection end’s release timer to another value, set
  10680. bit 2 of the atpFlags field in the parameter block for the PSendRequest or the
  10681. PNSendRequest function and add a new byte field to the parameter block at offset
  10682. 50—the TRelTime field. (The PSendRequest and PNSendRequest functions use the
  10683. SendRequestParm variant of the ATP parameter block.) Here is the ATP parameter
  10684. block for the PSendRequest and PNSendRequest functions:
  10685.  
  10686.    TYPE ATPParamBlock =
  10687.         PACKED RECORD                     {extended parameter block } 
  10688.                                           { for PSendRequest and }
  10689.                                           { PNSendRequest}
  10690.            qLink:           QElemPtr;     {next queue entry}
  10691.            qType:           Integer;      {queue type}
  10692.            ioTrap:          Integer;      {routine trap}
  10693.            ioCmdAddr:       Ptr;          {routine address}
  10694.            ioCompletion:    ProcPtr;      {completion routine}
  10695.            ioResult:        OsErr;        {result code}
  10696.            userData:        LongInt;      {ATP user bytes}
  10697.            reqTID:          Integer;      {request transaction ID}
  10698.            ioRefNum:        Integer;      {driver reference number}
  10699.            csCode:          Integer;      {primary command code}
  10700.            atpSocket:       Byte;         {currBitMap or socket number}
  10701.            atpFlags:        Byte;         {control information - set bit 2 }
  10702.                                           { for extended parameter block}
  10703.            addrBlock:       AddrBlock;    {source socket address}
  10704.            reqLength:       Integer;      {request size in bytes}
  10705.            reqPointer:      Ptr;          {pointer to request data}
  10706.            bdsPointer:      Ptr;          {pointer to response Buffer }
  10707.                                           { Data Structure}
  10708.            numOfBuffs:      Byte;         {number of responses expected}
  10709.            timeOutVal:      Byte;         {timeout interval}
  10710.            numOfResps:      Byte;         {number of responses }
  10711.                                           { actually received}
  10712.            retryCount:      Byte;         {number of retries}
  10713.            intBuff:         Integer;      {used internally for PNSendRequest}
  10714.            TRelTime:        Byte          {release timer setting}
  10715.         end;
  10716.  
  10717. The lower three bits of the TRelTime field indicate the time to which the
  10718. release timer is to be set, as follows:
  10719.  
  10720.    TRelTime field                   Setting of release timer
  10721.  
  10722.     000                                         30 seconds
  10723.     001                                         1 minute
  10724.     010                                         2 minutes
  10725.     011                                         4 minutes
  10726.     100                                         8 minutes
  10727.  
  10728.    Note:  The nodes at both ends of the ATP connection must be running AppleTalk
  10729.    Phase 2 drivers for this feature to work.
  10730.  
  10731. XO service, the release timer, and the SendRequest function are described in the
  10732. AppleTalk Manager chapter of Volume II. The ATP parameter block and the
  10733. PNSendRequest function are described in the AppleTalk Manager chapter of Volume
  10734. V.
  10735.  
  10736. _______________________________________________________________________________
  10737.  
  10738. æKY The….XPP…Driver…Volume…VI
  10739. æC »The .XPP Driver Volume VI                                            AppleTalk Manager
  10740. _______________________________________________________________________________
  10741.  
  10742. The .XPP driver provides these functions that return information about zones:
  10743.  
  10744.   •  The GetMyZone function returns the AppleTalk zone name of the node on
  10745.       which your application is running. This function works for both extended
  10746.       and
  10747.       nonextended networks.
  10748.  
  10749.   •  The GetLocalZones function returns a list of zone names on the network that
  10750.       includes the node on which your application is running. This function
  10751.       works
  10752.       for extended networks only.
  10753.  
  10754.   •  The GetZoneList function returns a complete list of zones on the internet.
  10755.  
  10756.    Note:  Before the AppleTalk Phase 2 version of the .XPP driver, you had to
  10757.    use
  10758.    AppleTalk Transaction Protocol (ATP) to obtain zone information and request
  10759.    it
  10760.    directly from a router. The Zone Information Protocol (ZIP) functions
  10761.    provided
  10762.    by the new version of the .XPP driver make it much easier for you to obtain
  10763.    this
  10764.    information. To ensure compatibility with future versions of AppleTalk, you
  10765.    should always use the functions described in this section to obtain zone
  10766.    information. 
  10767.  
  10768. For the GetMyZone, GetLocalZones, and GetZoneList functions, the .XPP driver
  10769. uses the xCallParam variant to the XPP parameter block.
  10770.  
  10771.    TYPE XPPParamBlock = 
  10772.         PACKED RECORD
  10773.            qLink:          QElemPtr;   {next queue entry}
  10774.            qType:          Integer;    {queue type}
  10775.            ioTrap:         Integer;    {routine trap}
  10776.            ioCmdAddr:      Ptr;        {routine address}
  10777.            ioCompletion:   ProcPtr;    {completion routine}
  10778.            ioResult:       OsErr;      {result code}
  10779.            cmdResult:      LongInt;    {command result}
  10780.            ioVRefNum:      Integer;    {volume reference number}
  10781.            ioRefNum:       Integer;    {driver reference number}
  10782.            csCode:         Integer;    {primary command code}
  10783.            CASE XPPPrmBlkType OF
  10784.               xCallParam
  10785.                 xppSubCode:   Integer;    {secondary command code}
  10786.                 xppTimeOut:   Byte;       {timeout period for .XPP}
  10787.                 xppRetry:     Byte;       {retry count}
  10788.                 filler1:      Integer;    {reserved}
  10789.                 zipBuffPtr:   Ptr;        {returned zone names}
  10790.                 zipNumZones:  Integer;    {number of zones returned}
  10791.                 zipLastFlag:  Byte;       {nonzero when all zone }
  10792.                                           { names have been returned}
  10793.                 filler2       Byte;       {reserved}
  10794.                 zipInfoField: packed array[1..70] of Byte
  10795.                                           {reserved for use by .XPP}
  10796.         END;
  10797.         XPPParmBlkPtr = ^XPPParamBlock;
  10798.  
  10799. As for all other AppleTalk Manager preferred interface functions, the MPW
  10800. interface calls the Device Manager PBControl function to implement these ZIP
  10801. protocol functions. The qLink, qType, ioTrap, ioCmdAddr, and ioVRefNum fields
  10802. are filled in by the Device Manager; your application should not have to set or
  10803. read these fields. The ioResult field returns the result of the function. If you
  10804. call the function asynchronously, the Device Manager sets this field to 1 as
  10805. soon as you call the function, and it changes the field to the actual result
  10806. code when the function completes execution. The ioCompletion field is a pointer
  10807. to a completion routine that you can provide; the Device Manager calls your
  10808. completion routine when it completes execution of the PBControl function. If you
  10809. are not providing a completion routine, specify NIL for this field. 
  10810.  
  10811. The value of the ioRefNum field is returned by the OpenDriver function; you must
  10812. provide this value in each call to an .XPP driver routine. The csCode and
  10813. xppSubCode fields specify the command to be executed; the MPW Pascal interface
  10814. fills in these fields for you.The .XPP zone information functions do not use the
  10815. cmdResult field.
  10816.  
  10817. _______________________________________________________________________________
  10818.  
  10819. æKY Using…the….XPP…Driver…to…Obtain…Information…About…Zones
  10820. æC »Using the .XPP Driver to Obtain Information About Zones              AppleTalk Manager
  10821. _______________________________________________________________________________
  10822.  
  10823. The Zone Information Protocol (ZIP) obtains the zone information by using the
  10824. AppleTalk Transaction Protocol (ATP) to send an information request to a router.
  10825. The xppTimeOut field specifies the amount of time, in seconds, that the .ATP
  10826. driver should wait between attempts to obtain the data. The xppRetry field
  10827. specifies the number of times the .ATP driver should attempt to obtain the data
  10828. before returning the reqFailed (request failed) result code. 
  10829.  
  10830. The zipBuffPtr field is a pointer to a data buffer that you must allocate. This
  10831. buffer must be 578 bytes for the GetZoneList and GetLocalZones functions and 33
  10832. bytes for the GetMyZone function. ZIP returns the zone names (as a packed array
  10833. of packed Pascal strings) into this buffer. The zipNumZones field returns the
  10834. actual number of zone names that ZIP placed in the buffer. You must set the
  10835. zipLastFlag field to 0 (FALSE) before you execute the GetZoneList or
  10836. GetLocalZones functions. If the zipLastFlag parameter is still 0 when the
  10837. command has completed execution, then ZIP is waiting to return more zone names.
  10838. In this case you must empty the buffer (or allocate a new one) and call the
  10839. GetZoneList or GetLocalZones function again immediately. When there are no more
  10840. zone names to return, ZIP sets the zipLastFlag field to a nonzero (TRUE) value.
  10841.  
  10842. The zipInfoField field is a 70-byte data buffer that you must allocate for use
  10843. by the .XPP driver. The first time you call any of these functions, you must set
  10844. the first word of this field to 0. You must not change any values in this field
  10845. subsequently.
  10846.  
  10847. Listing 32-2 illustrates the use of the GetZoneList function. The GetLocalZones
  10848. function operates in exactly the same fashion.
  10849.  
  10850. ¿ Listing 32-2   Using the GetZoneList function
  10851.  
  10852. PROCEDURE doGetZoneList;
  10853.  
  10854. VAR
  10855.    myXPPPB:  XPPParamBlock;      {.XPP parameter block}
  10856.    myErr:    OSErr;  
  10857.   
  10858. BEGIN
  10859.    WITH myXPPPB DO
  10860.    BEGIN
  10861.       xppTimeOut := 3;               {timeout period for .XPP}
  10862.       xppRetry := 4;                 {retry count}
  10863.       zipBuffPtr := NewPtr(578);     {zone names returned here}
  10864.       zipLastFlag := 0;              {set to 0 the first time through}
  10865.       zipInfoField[1] := 0;
  10866.       zipInfoField[2] := 0;          {first word is 0 the first }
  10867.                                      { time through}
  10868.   END;
  10869.   myErr := noErr;
  10870.  
  10871. {Check the zipNumZones field to determine how many zone names }
  10872. { have been returned in the buffer.  Append the zone names to the }
  10873. { end of your own buffer before returning to read more zone names.}
  10874.  
  10875.   {loop to get all of the zone names}
  10876.   WHILE (myXPPPB.zipLastFlag = 0) & (myErr = noErr) DO
  10877.   BEGIN
  10878.      myErr := GetZoneList(@myXPPPB, FALSE);
  10879.      EmptyDataBuf(@myXPPPB);      {your routine to empty }
  10880.                                   { data buffer}
  10881.   END;
  10882.   YourZIPProc(@myXPPPB);          {your routine to process names}
  10883.   IF myErr <> noErr THEN DoError(myErr);  
  10884.                                   {there's an error}
  10885.   DisposPtr(myXPPPB.zipBuffPtr);  {give space back}
  10886. END;
  10887.  
  10888. Listing 32-3 illustrates the use of the GetMyZone function. 
  10889.  
  10890. ¿ Listing 32-3   Using the GetMyZone function
  10891.  
  10892. PROCEDURE doGetMyZone;
  10893.  
  10894. VAR
  10895.    myXPPPB:      XPPParamBlock;    {.XPP parameter block}
  10896.    myZoneName:   ARRAY[1..33] OF CHAR;
  10897.    myErr:        OSErr;  
  10898.   
  10899. BEGIN 
  10900.    WITH myXPPPB DO
  10901.    BEGIN
  10902.       xppTimeOut := 3;            {timeout period for .XPP}
  10903.       xppRetry := 4;              {retry count}
  10904.       zipBuffPtr := @myZoneName;  {zone name returned here}
  10905.       zipInfoField[1] := 0;
  10906.       zipInfoField[2] := 0;       {first word is 0 the first }
  10907.                                   { time through}
  10908.   END;
  10909.   myErr := GetMyZone(@myXPPPB, FALSE);
  10910.   IF myErr <> noErr THEN DoError(myErr);  
  10911.                                   {there's an error}
  10912. END;                
  10913. _______________________________________________________________________________
  10914.  
  10915. æKY Obtaining…Zone…Information
  10916. æC »Obtaining Zone Information                                           AppleTalk Manager
  10917. _______________________________________________________________________________
  10918.  
  10919. The .XPP driver provides three functions that obtain information about zones.
  10920. All three functions use the Zone Information Protocol (ZIP) to return the names
  10921. of zones. 
  10922.  
  10923.           _________________________________________________
  10924.  
  10925.            Assembly-language note:  The .XPP driver functions all use the same 
  10926.            value (xCall, which is equal to 246) for the csCode parameter to the 
  10927.            XPP parameter block. The xCall routine uses the value of the 
  10928.            xppSubCode parameter to distinguish between the functions, as 
  10929.            follows:
  10930.  
  10931.             Function                    xppSubCode                    Value
  10932.             GetMyZone               zipGetMyZone                    7
  10933.             GetLocalZones          zipGetLocalZones              5
  10934.             GetZoneList               zipGetZoneList                  6
  10935.           _________________________________________________
  10936.  
  10937. FUNCTION GetMyZone (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10938.  
  10939.    Parameter block
  10940.         ¨         16       ioResult                word        result code 
  10941.         Æ         26       csCode                   word        routine
  10942.         selector; always xCall
  10943.         Æ         28       xppSubCode         word        routine selector;
  10944.         zipGetMyZone
  10945.         Æ         30       xppTimeOut         byte         retry interval in
  10946.         seconds
  10947.         Æ         31       xppRetry                byte         retry count
  10948.         Æ         34      zipBuffPtr               long       pointer to data
  10949.         buffer
  10950.         Æ         42       zipInfoField  70    bytes       for use by ZIP; first
  10951.         word set to 0
  10952.  
  10953. The GetMyZone function returns only the AppleTalk zone name of the node on which
  10954. your application is running.
  10955.  
  10956. The ioResult parameter returns the result of the function. If you call the
  10957. function asynchronously, the function sets this field to 1 as soon as it begins
  10958. execution, and it changes the field to the actual result code when it completes
  10959. execution. The csCode and xppSubCode parameters are routine selectors and are
  10960. automatically set by the MPW interface to xCall and zipGetMyZone for this
  10961. function. The xppTimeOut field specifies the amount of time, in seconds, that
  10962. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  10963. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  10964. specifies the number of times the .ATP driver should attempt to obtain the data
  10965. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  10966. for the xppRetry field usually works well. 
  10967.  
  10968. The zipBuffPtr is a pointer to a 33-byte data buffer that you must allocate. ZIP
  10969. returns the zone name into this buffer as a Pascal string. The zipInfo field is
  10970. a 70-byte data buffer that you must allocate for use by ZIP. You must set the
  10971. first word of this buffer to 0 before you call the GetMyZone function.
  10972.  
  10973.    Result codes
  10974.           noErr                          0      No error
  10975.           noBridgeErr          –93      No router is available
  10976.           reqFailed            –1096      Request to contact router failed;
  10977.           retry count exceeded 
  10978.           tooManyReqs   –1097      Too many concurrent requests
  10979.           noDataArea      –1104      Too many outstanding ATP calls
  10980.  
  10981. FUNCTION GetLocalZones (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  10982.  
  10983.   Parameter block
  10984.        ¨  16       ioResult                 word      result code 
  10985.        Æ  26       csCode                    word      routine selector; always
  10986.        xCall
  10987.        Æ  28       xppSubCode          word      routine selector;
  10988.        zipGetLocalZones
  10989.        Æ  30       xppTimeOut          byte       retry interval in seconds
  10990.        Æ  31       xppRetry                 byte       retry count
  10991.        Æ  34       zipBuffPtr              long       pointer to data buffer
  10992.        ¨  38       zipNumZones      word     number of names returned
  10993.        ¨  40       zipLastFlag             byte       nonzero if no more names
  10994.        Æ  42        zipInfoField  70    bytes     for use by ZIP; first word set
  10995.        to 0
  10996.  
  10997. The GetLocalZones function returns a list of all the zone names on the local
  10998. network; that is, the network that includes the node on which your application
  10999. is running.
  11000.  
  11001. The ioResult parameter returns the result of the function. If you call the
  11002. function asynchronously, the function sets this field to 1 as soon as it begins
  11003. execution, and it changes the field to the actual result code when it completes
  11004. execution. The csCode and xppSubCode parameters are routine selectors and are
  11005. automatically set by the MPW interface to xCall and zipGetLocalZones for this
  11006. function. The xppTimeOut field specifies the amount of time, in seconds, that
  11007. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  11008. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  11009. specifies the number of times the .ATP driver should attempt to obtain the data
  11010. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  11011. for the xppRetry field usually works well.
  11012.  
  11013. The zipBuffPtr field is a pointer to a 578-byte data buffer that you must
  11014. allocate. ZIP returns the zone names into this buffer as a packed array of
  11015. packed Pascal strings. The zipNumZones parameter returns the number of zone
  11016. names that ZIP placed in the data buffer. 
  11017.  
  11018. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  11019. for your network. If the zipLastFlag field is still 0 when the GetLocalZones
  11020. function has completed execution, you must empty the data buffer pointed to by
  11021. the zipBuffPtr parameter and immediately call the GetLocalZones function again
  11022. without changing the value in the zipInfoField parameter. The zipInfoField
  11023. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  11024. must set the first word of this buffer to 0 before you call the GetLocalZones
  11025. function the first time, and you must not change the contents of this field
  11026. thereafter.
  11027.  
  11028.    Result codes
  11029.          noErr                           0       No error
  11030.          noBridgeErr            –93      No router is available
  11031.          reqFailed              –1096      Request to contact router failed;
  11032.          retry count exceeded
  11033.          tooManyReqs     –1097      Too many concurrent requests
  11034.          noDataArea        –1104      Too many outstanding ATP calls
  11035.  
  11036. FUNCTION GetZoneList (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  11037.  
  11038.    Parameter block
  11039.         ¨      16       ioResult                word           result code 
  11040.         Æ      26       csCode                    word          routine
  11041.         selector; always xCall
  11042.         Æ      28       xppSubCode         word           routine selector;
  11043.         zipGetZoneList
  11044.         Æ      30      xppTimeOut          byte             retry interval in
  11045.         seconds
  11046.         Æ      31       xppRetry                byte             retry count
  11047.         Æ      34       zipBuffPtr             long             pointer to data
  11048.         buffer
  11049.         ¨      38       zipNumZones    word            number of names returned
  11050.         ¨      40       zipLastFlag            byte             nonzero if no
  11051.         more names
  11052.         Æ      42       zipInfoField         70 bytes        for use by ZIP;
  11053.         first word set to 0
  11054.  
  11055. The GetZoneList function returns a complete list of all the zone names on the
  11056. internet. To obtain a list of only the zone names on the local network, use the
  11057. GetLocalZones function instead. 
  11058.  
  11059. The ioResult parameter returns the result of the function. If you call the
  11060. function asynchronously, the function sets this field to 1 as soon as it begins
  11061. execution, and it changes the field to the actual result code when it completes
  11062. execution. The csCode and xppSubCode parameters are routine selectors and are
  11063. automatically set by the MPW interface to xCall and zipGetZoneList for this
  11064. function. The xppTimeOut field specifies the amount of time, in seconds, that
  11065. the .ATP driver should wait between attempts to obtain the data. A value of 3 or
  11066. 4 for the xppTimeOut field generally gives good results. The xppRetry field
  11067. specifies the number of times the .ATP driver should attempt to obtain the data
  11068. before returning the ReqFailed (request failed) result code. A value of 3 or 4
  11069. for the xppRetry field usually works well.
  11070.  
  11071. The zipBuffPtr field is a pointer to a 578-byte data buffer that you must
  11072. allocate. ZIP returns the zone names into this buffer as Pascal strings. The
  11073. zipNumZones parameter returns the number of zone names that ZIP placed in the
  11074. data buffer. 
  11075.  
  11076. The .XPP driver sets the zipLastFlag field to 1 if there are no more zone names
  11077. for the internet. If the zipLastFlag field is still 0 when the GetZoneList
  11078. function has completed execution, you must empty the data buffer pointed to by
  11079. the zipBuffPtr parameter and immediately call the GetZoneList function again
  11080. without changing the value in the zipInfoField parameter. The zipInfoField
  11081. parameter is a 70-byte data buffer that you must allocate for use by ZIP. You
  11082. must set the first word of this buffer to 0 before you call the GetZoneList
  11083. function the first time, and not change the contents of this field thereafter.
  11084.  
  11085. If you use the GetZoneList function on an nonextended network, it returns the
  11086. reqFailed result code.
  11087.  
  11088.    Result codes
  11089.           noErr                            0     No error
  11090.           noBridgeErr            –93     No router is available
  11091.           reqFailed              –1096     Request to contact router failed;
  11092.           retry count exceeded
  11093.           tooManyReqs      –1097     Too many concurrent requests
  11094.           noDataArea         –1104     Too many outstanding ATP calls
  11095. _______________________________________________________________________________
  11096.  
  11097. æKY Appletalk…Data…Stream…Protocol…(adsp)…Volume…VI
  11098. æC »Appletalk Data Stream Protocol (adsp) Volume VI                      AppleTalk Manager
  11099. _______________________________________________________________________________
  11100.  
  11101. One of the significant new features of AppleTalk included as part of system
  11102. software version 7.0 is the AppleTalk Data Stream Protocol (ADSP), which
  11103. provides a full-duplex data stream connection between two nodes in an AppleTalk
  11104. internet. Like the AppleTalk Session Protocol, Printer Access Protocol, and
  11105. AppleTalk Transaction Protocol, ADSP uses the Datagram Delivery Protocol to send
  11106. its data over the internet. Therefore, even though ADSP appears to its clients
  11107. to handle data as a stream of bytes, the data is actually transmitted and
  11108. received by DDP in packets. ADSP takes advantage of this fact by including
  11109. control and status information in the DDP packet header. You can use the .DSP
  11110. driver routines described in “.DSP Driver Routines,” later in this chapter, to
  11111. control an ADSP connection. The .DSP driver takes care of implementation of ADSP
  11112. for you. 
  11113.  
  11114. Every ADSP connection is between two sockets in an AppleTalk internet. Each
  11115. socket can maintain concurrent ADSP connections with several other sockets, but
  11116. there can be only one ADSP connection between any two sockets at one time. When
  11117. a pair of sockets establishes an ADSP connection, each socket client initializes
  11118. and maintains a certain amount of control and state information that it uses for
  11119. synchronizing communication with the other socket client and for error checking.
  11120.  
  11121.  
  11122. The combination of a socket and the ADSP information maintained by the socket
  11123. client is referred to as a connection end. When two connection ends establish
  11124. communication, the connection is considered an open connection. When both
  11125. connection ends terminate the link and dispose of the connection information
  11126. each maintains, the connection is considered a closed connection. If one
  11127. connection end is established but the other connection end is unreachable or has
  11128. disposed of its connection information, the connection is considered a half-open
  11129. connection. No communication can occur over a half-open or closed connection. To
  11130. prevent a half-open connection from tying up resources, ADSP automatically
  11131. closes any half-open connection that cannot reestablish communications within 2
  11132. minutes. 
  11133.  
  11134. _______________________________________________________________________________
  11135.  
  11136. æKY Using…ADSP
  11137. æC »Using ADSP                                                           AppleTalk Manager
  11138. _______________________________________________________________________________
  11139.  
  11140. You can use ADSP to implement a data stream connection between any two sockets
  11141. on an internet. (Note that although there can be only one ADSP connection
  11142. between any two sockets, a single socket can maintain connections with several
  11143. other sockets.) This section describes how to open, maintain, and close a
  11144. connection between two sockets on an internet. It also describes how to
  11145. establish and use a connection listener; that is, a connection end that waits
  11146. passively to receive a connection request and then passes the connection request
  11147. on to its client, the connection server. Finally, this section describes how to
  11148. write a routine (referred to as a user routine ) that ADSP calls when your
  11149. connection end receives an unsolicited connection event. 
  11150.  
  11151. _______________________________________________________________________________
  11152.  
  11153. æKY The…ADSP…Connection…Control…Block
  11154. æC »The ADSP Connection Control Block                                    AppleTalk Manager
  11155. _______________________________________________________________________________
  11156.  
  11157. When you establish an ADSP connection end, you must allocate a nonrelocatable
  11158. block of memory for, and provide a pointer to, a connection control block (CCB)
  11159. data structure, which is used by ADSP to store state information about the
  11160. connection end. You may read the fields in the CCB to obtain information about
  11161. the connection end, but you are not allowed to write to any of the fields except
  11162. one, the userFlags field. The CCB requires 242 bytes and is defined by the TRCCB
  11163. data type.
  11164.  
  11165.    TYPE TRCCB = 
  11166.         PACKED RECORD
  11167.            ccbLink:         TPCCB;            {link to next CCB}
  11168.            refNum:          Integer;          {reference number}
  11169.            state:           Integer;          {state of the connection end}
  11170.            userFlags:       Byte;             {user flags for connection}
  11171.            localSocket:     Byte;             {local socket number}
  11172.            remoteAddress:   AddrBlock;        {remote end internet address}
  11173.            attnCode:        Integer;          {attention code received}
  11174.            attnSize:        Integer;          {size of attention data}
  11175.            attnPtr:         Ptr;              {pointer to attention data}
  11176.            reserved:        PACKED ARRAY[1..220] OF Byte
  11177.                                               {reserved for use by ADSP}
  11178.         END;
  11179.  
  11180. The internet address of the remote connection end is defined in the TRCCB record
  11181. by the AddrBlock data type:
  11182.  
  11183. TYPE AddrBlock = 
  11184.      PACKED RECORD
  11185.        aNet:                Integer;          {network number}
  11186.        aNode:               Byte;             {node ID}
  11187.        aSocket:             Byte              {socket number}
  11188.      END; 
  11189.  
  11190. Field descriptions
  11191.  
  11192. ccbLink           A pointer to the next CCB. This field is for use by ADSP only.
  11193.  
  11194. refNum         The reference number of the CCB. This number is assigned by ADSP
  11195.                         when you establish the connection end.
  11196.  
  11197. state                The state of the connection end, as follows:
  11198.  
  11199.                          State                Value         Meaning
  11200.  
  11201.                          sListening       1                 The socket is a
  11202.                          connection listening socket;
  11203.                                                                       that is, a
  11204.                                                                       socket
  11205.                                                                       that
  11206.                                                                       accepts
  11207.                                                                       ADSP
  11208.                                                                       requests
  11209.                                                                       to
  11210.                                                                       open
  11211.  
  11212.                                                                       and passes
  11213.                                                                       them on to
  11214.                                                                       a
  11215.                                                                       socket
  11216.                                                                       client.
  11217.                                                                       This state
  11218.                                                                       is
  11219.                                                                       ordinarily
  11220.                                                                       used
  11221.                                                                       only by
  11222.                                                                       connection
  11223.                                                                       servers.
  11224.  
  11225.                           sPassive          2                 The socket client
  11226.                           is inactive but capable of
  11227.                                                                        accepting
  11228.                                                                        an ADSP
  11229.                                                                        request
  11230.                                                                        to open a
  11231.  
  11232.                                                                        Unlike a
  11233.  
  11234.                                                                        listening
  11235.                                                                        socket,
  11236.                                                                        which
  11237.                                                                        passes
  11238.                                                                        the
  11239.  
  11240.  
  11241.                                                                        request
  11242.                                                                        on to a
  11243.                                                                        routine
  11244.                                                                        that can
  11245.                                                                        establish
  11246.                                                                        the
  11247.  
  11248.                                                                        on any
  11249.                                                                        socket, a
  11250.                                                                        socket
  11251.                                                                        client in
  11252.                                                                        the
  11253.                                                                        sPassive
  11254.                                                                        state can
  11255.                                                                        accept an
  11256.  
  11257.                                                                        request
  11258.                                                                        only to
  11259.                                                                        establish
  11260.                                                                        itself as
  11261.                                                                        a
  11262.  
  11263.                                                                        end.
  11264.  
  11265.                            sOpening        3                The socket client
  11266.                            has sent an
  11267.  
  11268.                                                                        request
  11269.                                                                        and is
  11270.                                                                        waiting
  11271.                                                                        for
  11272.  
  11273.  
  11274.  
  11275.                             sOpen             4                 The connection
  11276.                             is open.
  11277.  
  11278.                             sClosing         5                 The socket client
  11279.                             has requested that ADSP
  11280.                                                                         close
  11281.                                                                         the
  11282.  
  11283.                                                                         and ADSP
  11284.                                                                         is
  11285.                                                                         sending
  11286.                                                                         data or
  11287.                                                                         waiting
  11288.                                                                         for
  11289.  
  11290.                                                                         of data
  11291.                                                                         it has
  11292.                                                                         sent
  11293.                                                                         before
  11294.                                                                         closing
  11295.                                                                         the
  11296.  
  11297.  
  11298.  
  11299.                             sClosed            6                Either
  11300.                             connection end or ADSP has closed
  11301.                                                                         the
  11302.  
  11303.  
  11304.  
  11305. userFlags          Flags that indicate an unsolicited connection event has
  11306. occurred. An
  11307.                            unsolicited connection event is an event initiated by
  11308.                            ADSP or the
  11309.                            remote connection end that is not in response to any
  11310.                            .DSP routine
  11311.                            that you executed.  .i.AppleTalk Data Stream
  11312.                            Protocol:user flags 32-
  11313.  
  11314.                            Each time an unsolicited connection event occurs,
  11315.                            ADSP sets a flag
  11316.                            in the userFlags field of the CCB and calls the
  11317.                            routine you specified
  11318.                            in the userRoutine parameter to the dspInit routine
  11319.                            (if any). The       
  11320.                            user routine must read the userFlags field and then
  11321.                            clear the flag to
  11322.                            0. ADSP cannot notify your routine of future events
  11323.                            unless you clear
  11324.                            the flag after each event.
  11325.  
  11326.                            ADSP recognizes four types of unsolicited connection
  11327.                            events, one
  11328.                             corresponding to each of the flags in this field.
  11329.                             The events and flags
  11330.                             are defined as follows, where bit 7 is the most
  11331.                             significant bit:
  11332.  
  11333.                             Event              Flag bit          Meaning
  11334.  
  11335.                               eClosed            7                    ADSP has
  11336.                               been informed by the remote
  11337.  
  11338.  
  11339.  
  11340.  
  11341.  
  11342.  
  11343.  
  11344.  
  11345.  
  11346.  
  11347.  
  11348.  
  11349.  
  11350.  
  11351.  
  11352.                               eTearDown      6                  ADSP has
  11353.                               determined that the remote
  11354.  
  11355.  
  11356.                                                                               is
  11357.  
  11358.  
  11359.  
  11360.                                                                               so
  11361.  
  11362.  
  11363.  
  11364.  
  11365.  
  11366.  
  11367.                                eAttention       5                  ADSP has
  11368.                                received an attention
  11369.  
  11370.  
  11371.  
  11372.  
  11373.  
  11374.  
  11375.  
  11376.  
  11377.  
  11378.                               eFwdReset         4                 ADSP has
  11379.                               received a forward reset
  11380.  
  11381.  
  11382.  
  11383.  
  11384.  
  11385.  
  11386.  
  11387.  
  11388.  
  11389.  
  11390.  
  11391.  
  11392.  
  11393.  
  11394.  
  11395.  
  11396.  
  11397.  
  11398.                                                                               in
  11399.  
  11400.  
  11401.  
  11402.  
  11403.  
  11404.  
  11405.  
  11406.  
  11407.  
  11408.  
  11409.  
  11410.  
  11411.  
  11412.  
  11413.                                none                   3–0            Reserved.
  11414.  
  11415. localSocket          The socket number through which DDP transmits and receives 
  11416.                                the ADSP packets.
  11417.  
  11418. remoteAddress   The internet address of the socket used by the remote connection
  11419.                                 end.
  11420.  
  11421. attnCode               The attention code received by ADSP when the remote
  11422.                                 connection end sends an attention message.
  11423.  
  11424. attnSize                 The size of the attention message received by ADSP when
  11425. the
  11426.                                 remote connection end sends an attention
  11427.                                 message.
  11428.  
  11429. attnPtr                    A pointer to a buffer containing the attention
  11430. message received
  11431.                                  by ADSP from the remote connection end.
  11432.  
  11433. reserved                 A data buffer reserved for use by ADSP.
  11434.  
  11435. _______________________________________________________________________________
  11436.  
  11437. æKY The….DSP…Parameter…Block
  11438. æC »The .DSP Parameter Block                                             AppleTalk Manager
  11439. _______________________________________________________________________________
  11440.  
  11441. You execute the .DSP routines by calling the Device Manager’s PBControl
  11442. function. Each time you call a .DSP routine, you provide a pointer to a
  11443. parameter block that includes all of the parameters needed by that command. 
  11444.  
  11445. The .DSP parameter block, defined by the DSPParamBlock data type, is a variant
  11446. parameter block for the PBControl function.
  11447.  
  11448.    TYPE DSPParamBlock = 
  11449.        PACKED RECORD
  11450.           qLink:            QElemPtr;        {next queue entry}
  11451.           qType:            Integer;         {queue type}
  11452.           ioTrap:           Integer;         {routine trap}
  11453.           ioCmdAddr:        Ptr;             {routine address}
  11454.           ioCompletion:     ProcPtr;         {completion routine}
  11455.           ioResult:         OsErr;           {result code}
  11456.           ioNamePtr:        StringPtr;       {used only for dspOpen}
  11457.           ioVRefNum:        Integer;         {volume reference number}
  11458.           ioCRefNum:        Integer;         {driver reference number}
  11459.           csCode:           Integer;         {primary command code}
  11460.           qStatus:          LongInt;         {reserved for ADSP}
  11461.           ccbRefNum:        Integer;         {CCB reference number}
  11462.  
  11463.           CASE Integer OF
  11464.           dspInit,
  11465.           dspCLInit:
  11466.           (
  11467.              ccbPtr:        TPCCB;           {pointer to CCB}
  11468.              userRoutine:   ProcPtr;         {pointer to user routine}
  11469.              sendQSize:     Integer;         {size of send queue}
  11470.              sendQueue:     Ptr;             {pointer to send queue}
  11471.              recvQSize:     Integer;         {size of receive queue}
  11472.              recvQueue:     Ptr;             {pointer to receive queue}
  11473.              attnPtr:       Ptr;             {pointer to attention- }
  11474.                                              { message buffer}
  11475.              localSocket:   Byte;            {local socket number}
  11476.              filler1:       Byte;            {filler for proper alignment}
  11477.            );
  11478.  
  11479.            dspOpen,
  11480.            dspCLListen,
  11481.            dspCLDeny:
  11482.           (
  11483.              localCID:       Integer;        {local connection ID}
  11484.              remoteCID:      Integer;        {remote connection ID}
  11485.              remoteAddress:  AddrBlock;      {remote internet address}
  11486.              filterAddress:  AddrBlock;      {address filter}
  11487.              sendSeq:        LongInt;        {send sequence number}
  11488.              sendWindow:     Integer;        {size of remote buffer}
  11489.              recvSeq:        LongInt;        {receive sequence number}
  11490.              attnSendSeq:    LongInt;        {attention send seq number}
  11491.              attnRecvSeq:    LongInt;        {attention receive seq num}
  11492.              ocMode:         Byte;           {connection opening mode}
  11493.              ocInterval:     Byte;           {interval bet open requests}
  11494.              ocMaximum:      Byte;           {retries of open conn req}
  11495.              filler2:        Byte;           {filler for proper alignment}
  11496.            );
  11497.  
  11498.            dspClose,
  11499.            dspRemove:
  11500.           (
  11501.              abort:          Byte;           {abort send requests}
  11502.              filler3:        Byte;           {filler for proper alignment}
  11503.           );
  11504.  
  11505.           dspStatus:
  11506.           (
  11507.              statusCCB:      TPCCB;          {pointer to CCB}
  11508.              sendQPending:   Integer;        {bytes waiting in send queue}
  11509.              sendQFree:      Integer;        {available send-queue buffer}
  11510.              recvQPending:   Integer;        {bytes in receive queue}
  11511.              recvQFree:      Integer;        {avail receive-queue buffer}
  11512.           )
  11513.  
  11514.           dspRead,
  11515.           dspWrite:
  11516.           (
  11517.              reqCount:       Integer;        {requested number of bytes}
  11518.              actCount:       Integer;        {actual number of bytes}
  11519.              dataPtr:        Ptr;            {pointer to data buffer}
  11520.              eom:            Byte;           {1 if end of message}
  11521.              flush:          Byte;           {1 to send data now}
  11522.           )
  11523.   
  11524.           dspAttention:
  11525.           (
  11526.              attnCode:       Integer;         {client attention code}
  11527.              attnSize:       Integer;         {size of attention data}
  11528.              attnData        Ptr;             {pointer to attention data}
  11529.              attnInterval:   Byte;            {reserved}
  11530.              filler4:        Byte;            {filler for proper alignment}
  11531.           )
  11532.   
  11533.           dspOptions:
  11534.           (
  11535.              sendBlocking:   Integer;          {send-blocking threshold}
  11536.              sendTimer:      Byte;             {reserved}
  11537.              rtmtTimer:      Byte;             {reserved}
  11538.              badSeqMax:      Byte;             {retransmit advice threshold}
  11539.              useCheckSum:    Byte;             {DDP checksum for packets}
  11540.           )
  11541.   
  11542.           dspNewCID:
  11543.           (
  11544.              newCID:          Integer;          {new connection ID}
  11545.           )
  11546.        END;
  11547.  
  11548. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
  11549. in by the Device Manager; your application should not have to set or read these
  11550. fields. The ioResult field returns the result of the function. If you call the
  11551. routine asynchronously, the Device Manager sets this field to 1 as soon as you
  11552. call the routine and it changes the field to the actual result code when the
  11553. routine completes execution. The ioCompletion field is a pointer to a completion
  11554. routine that you can provide; the Device Manager calls your completion routine
  11555. when it completes execution of the PBControl function. If you are not providing
  11556. a completion routine, specify NIL for this field. 
  11557.  
  11558. The ioCRefNum field is returned by the OpenDriver function. You must specify
  11559. this number every time you call the .DSP driver. 
  11560.  
  11561. The csCode field specifies the command to be executed. You must fill in this
  11562. field before calling the PBControl function. You can use the following constants
  11563. as values for the csCode field: 
  11564.  
  11565. CONST  {ADSP routine selectors}
  11566.        dspInit       = 255;        {create a new connection end}
  11567.        dspRemove     = 254;        {remove a connection end}
  11568.        dspOpen       = 253;        {open a connection}
  11569.        dspClose      = 252;        {close a connection}
  11570.        dspCLInit     = 251;        {create a connection listener}
  11571.        dspCLRemove   = 250;        {remove a connection listener}
  11572.        dspCLListen   = 249;        {post a listener request}
  11573.        dspCLDeny     = 248;        {deny an open-connection request}
  11574.        dspStatus     = 247;        {get status of connection end}
  11575.        dspRead       = 246;        {read data from the connection}
  11576.        dspWrite      = 245;        {write data on the connection}
  11577.        dspAttention  = 244;        {send an attention message}
  11578.        dspOptions    = 243;        {set connection end options}
  11579.        dspReset      = 242;        {forward reset the connection}
  11580.        dspNewCID     = 241;        {generate a cid for a connection end} 
  11581.  
  11582. The qStatus field is reserved for use by ADSP. The ccbRefNum field is the
  11583. reference number of the CCB. The CCB reference number is returned by ADSP in
  11584. response to the dspInit routine. You must specify this number as a parameter to
  11585. every .DSP driver routine you call subsequently.
  11586.  
  11587. The remaining fields are used only for specific routines; each of these fields
  11588. is described in “.DSP Driver Routines” later in this chapter.
  11589.  
  11590. _______________________________________________________________________________
  11591.  
  11592. æKY Opening…and…Maintaining…an…ADSP…Connection
  11593. æC »Opening and Maintaining an ADSP Connection                           AppleTalk Manager
  11594. _______________________________________________________________________________
  11595.  
  11596. To use the AppleTalk Data Stream Protocol (ADSP) to establish and maintain a
  11597. connection between a socket on your local node and a remote socket, use the
  11598. following procedure:
  11599.  
  11600.    1.  Use the MPPOpen function to open the .MPP driver, and then use the
  11601.         OpenDriver function to open the .DSP driver. The OpenDriver function
  11602.         returns the reference number for the .DSP driver. You must supply this
  11603.         reference number each time you call the .DSP driver.
  11604.  
  11605.    2.  Allocate nonrelocatable memory for a connection control block (CCB), send
  11606.         and receive queues, and an attention message buffer. If you need to
  11607.         allocate the
  11608.         memory dynamically while the program is running, use the NewPtr routine.
  11609.         Otherwise, the way in which you allocate the memory depends on the
  11610.         compiler you are using. (Listing 32-4 at the end of this section shows
  11611.         how it’s
  11612.         done in Pascal). The memory that you allocate becomes the property of
  11613.         ADSP
  11614.         when you call the dspInit routine to establish a connection end. You
  11615.         cannot
  11616.         write any data to this memory except by calling ADSP, and you must
  11617.         ensure
  11618.         that the memory remains locked until you call the dspRemove routine to
  11619.         eliminate the connection end.
  11620.  
  11621.         The CCB is 242 bytes. The attention-message buffer must be 570 bytes.
  11622.         When
  11623.          you send bytes to a remote connection end, ADSP stores the bytes in a
  11624.          buffer
  11625.          called the send queue . Until the remote connection end acknowledges
  11626.          their
  11627.          receipt, ADSP keeps the bytes you sent in the send queue so that they
  11628.          are
  11629.          available to be retransmitted if necessary. When the local connection
  11630.          end
  11631.          receives bytes, it stores them in a buffer, called the receive queue,
  11632.          until you
  11633.          read them. The sizes you need for the send and receive queues depend on
  11634.          the
  11635.          lengths of the messages being sent. 
  11636.  
  11637.          ADSP does not transmit data from the remote connection end until there
  11638.          is
  11639.          room for it in your receive queue. If your send or receive queues are
  11640.          too small,
  11641.          they limit the speed with which you can transmit and receive data. A
  11642.          queue
  11643.          size of 600 bytes should work well for most applications. If you are
  11644.          using ADSP
  11645.          to send a continuous flow of data, a larger data buffer improves
  11646.          performance.
  11647.          If your application is sending or receiving the user’s keystrokes, a
  11648.          smaller
  11649.          buffer should be adequate. The constant minDSPQueueSize indicates the
  11650.          minimum queue size that you can use.
  11651.  
  11652.          If you are using a version of the .DSP driver prior to version 1.5, you
  11653.          must
  11654.          allocate send and receive queues that are 12% larger than the actual
  11655.          buffer
  11656.          sizes you need. You must do this in order to provide some extra space
  11657.          for use
  11658.          by the .DSP driver. Version 1.5 and later versions of the .DSP driver
  11659.          use a
  11660.          much smaller, and variable, portion of buffer space for overhead. The
  11661.          .DSP
  11662.          driver version number is stored in the low byte of the qFlags field,
  11663.          which is
  11664.          the first field in the dCtlQHdr field in the driver’s device control
  11665.          entry (DCE)
  11666.          data structure. Version 1.5 of the .DSP driver has a version number of
  11667.          4 in the
  11668.          DCE. The DCE is described in the Device Manager chapters of Volumes II
  11669.          and
  11670.          V.
  11671.  
  11672.    3.  Use the dspInit routine to establish a connection end. You must provide
  11673.         pointers to the CCB, send queue, receive queue, and attention-message
  11674.         buffer.
  11675.         You may also provide a pointer to the user routine that ADSP calls when
  11676.         your
  11677.         connection end receives an unsolicited connection event. User routines
  11678.         are
  11679.         discussed in “Writing a User Routine for Connection Events” later in
  11680.         this
  11681.         chapter.
  11682.  
  11683.          If there is a specific socket that you want to use for the connection
  11684.          end, you can
  11685.          specify the socket number in the localSocket parameter. If you want
  11686.          ADSP to
  11687.          assign the socket for you, specify 0 for the localSocket parameter.
  11688.          ADSP returns
  11689.          the socket number when the dspInit routine completes execution.
  11690.  
  11691.    4.  If you wish, you can use the NBPRegister function to add the name and
  11692.         address of your connection end to the node’s names table. The
  11693.         NBPRegister
  11694.         function is described in the AppleTalk Manager chapter of Volume II. 
  11695.  
  11696.    5.  You can use the dspOptions routine to set several parameters that control
  11697.    the
  11698.         behavior of the connection end. Because every parameter has a default
  11699.         value,
  11700.         the use of the dspOptions routine is optional. You can specify values
  11701.         for the
  11702.         following parameters:
  11703.  
  11704.           •  The sendBlocking parameter, which sets the maximum number of bytes
  11705.                that may accumulate in the send queue before ADSP sends a packet
  11706.                to the
  11707.                remote connection end. You can experiment with different values
  11708.                of the
  11709.                sendBlocking parameter to determine which provides the best
  11710.                performance. Under most circumstances, the default value of
  11711.                16 bytes gives
  11712.                good performance.
  11713.  
  11714.          •  The badSeqMax parameter, which sets the maximum number of
  11715.               out-of-sequence data packets that the local connection end can
  11716.               receive
  11717.               before requesting the remote connection end to retransmit the
  11718.               missing
  11719.               data. Under most circumstances, the default value of 3 provides
  11720.               good
  11721.               performance. 
  11722.  
  11723.          •  The useCheckSum parameter, which determines whether the Datagram
  11724.              Delivery Protocol (DDP) should compute a checksum and include it in
  11725.              each
  11726.              packet that it sends to the remote connection end. Using checksums
  11727.              slows
  11728.              communications slightly. Normally ADSP and DDP perform enough error
  11729.              checking to ensure safe delivery of all data. Set the useCheckSum
  11730.              parameter
  11731.              to 1 only if you feel that the network is highly unreliable.
  11732.  
  11733.    6.  Call the dspOpen routine to open the connection. The dspOpen routine has
  11734.         four possible modes of operation: ocAccept, ocEstablish, ocRequest, and
  11735.         ocPassive. Normally you use either the ocRequest or ocPassive mode. You
  11736.         must specify one of these four modes for the ocMode parameter when you
  11737.         call
  11738.         the dspOpen routine. 
  11739.  
  11740.        The ocAccept mode is used only by connection servers. The ocEstablish
  11741.        mode is
  11742.        used by routines that determine their connection-opening parameters and
  11743.        establish a connection independently of ADSP, but use ADSP to transmit
  11744.        and
  11745.        receive data.
  11746.  
  11747.         Use the ocRequest mode when you want to establish communications with a
  11748.         specific socket on the internet. When you execute the dspOpen routine in
  11749.         the
  11750.         ocRequest mode, ADSP sends an open-connection request to the address you
  11751.         specify. 
  11752.  
  11753.         If the socket to which you send the open-connection request is a
  11754.         connection
  11755.         listener, the connection server that operates that connection listener
  11756.         can
  11757.         choose any socket on the internet to be the connection end that responds
  11758.         to the
  11759.         open-connection request. To restrict the socket from which you will
  11760.         accept a
  11761.         response to your open-connection request, specify a value for the
  11762.         filterAddress
  11763.         parameter to the dspOpen routine. When your connection end receives a
  11764.         response from a socket that meets the restrictions of the filterAddress
  11765.         parameter, it acknowledges the response and ADSP completes the
  11766.         connection. 
  11767.  
  11768.         To use the ocRequest mode, you must know the complete internet address
  11769.         of
  11770.         the remote socket, and the ADSP client at that address must either be a
  11771.         connection listener or have executed the dspOpen routine in the
  11772.         ocPassive
  11773.         mode. You can use the PLookupName function to obtain a list of names of
  11774.         objects on the internet and to determine the internet address of a
  11775.         socket when
  11776.         you know its name. The PLookupName function is the preferred interface
  11777.         version of the NBPLookup function. The NBPLookup function is described
  11778.         in
  11779.         the AppleTalk Manager chapter of Volume II. The preferred interface is
  11780.         described in the AppleTalk Manager chapter of Volume V. Enhancements to
  11781.         the wildcard-lookup feature of the Name-Binding Protocol (NBP) are
  11782.         discussed
  11783.         in “A New NBP Wildcard Character” earlier in this chapter. 
  11784.  
  11785.         Use the ocPassive mode when you expect to receive an open-connection
  11786.         request from a remote socket. You can specify a value for the
  11787.         filterAddress
  11788.         parameter to restrict the network number, node ID, or socket number from
  11789.         which you will accept an open-connection request. When your connection
  11790.         end
  11791.          receives an open-connection request that meets the restrictions of the
  11792.         filterAddress parameter, it acknowledges the request and ADSP completes
  11793.         the
  11794.         connection. 
  11795.  
  11796.         You can poll the state field in the CCB to determine when the connection
  11797.         end
  11798.         is waiting to receive an open-connection request, when the connection
  11799.         end is
  11800.         waiting to receive an acknowledgment of an open-connection request, and
  11801.         when the connection is open. (The CCB is described in “The ADSP
  11802.         Connection
  11803.         Control Block” earlier in this chapter.) Alternatively, you can check
  11804.         the result
  11805.         code for the dspOpen routine when the routine completes execution. If
  11806.         the
  11807.         routine returns the noErr result code, then the connection is open.
  11808.  
  11809.    7.   Use the dspRead routine to read data that your connection end has
  11810.    received
  11811.          from the remote connection end. Use the dspWrite routine to send data
  11812.          to the
  11813.          remote connection end. Use the dspAttention routine to send attention
  11814.          messages to the remote connection end.
  11815.  
  11816.          The dspWrite routine places data in the send queue. ADSP is a
  11817.          full-duplex,
  11818.          symmetric communications protocol. You can send data at any time, and
  11819.          your
  11820.          connection end can receive data at any time, even at the same time as
  11821.          you are
  11822.          sending data. ADSP transmits the data in the send queue when one of the
  11823.          following conditions occurs:
  11824.  
  11825.            •  You call the dspWrite routine with the flush parameter set to a
  11826.            nonzero
  11827.                number.
  11828.  
  11829.            •  The number of bytes in the send queue equals or exceeds the
  11830.            blocking
  11831.                factor that you set with the dspOptions routine.
  11832.  
  11833.             •  The send timer expires. The send timer sets the maximum amount of
  11834.                  time that can pass before ADSP sends all unsent data in the
  11835.                  send queue to
  11836.                  the remote connection end. ADSP calculates the best value to
  11837.                  use for this
  11838.                  timer and sets it automatically.
  11839.  
  11840.             •  A connection event requires that the local connection end send an
  11841.                 acknowledgment packet to the remote connection end.
  11842.  
  11843.           If you send more data to the send queue than it can hold, the dspWrite
  11844.  
  11845.           routine does not complete execution until it has written all the data
  11846.           to the
  11847.           send queue. If you execute the dspWrite routine asynchronously, ADSP 
  11848.           returns control to your program and writes the data to the send queue
  11849.           as
  11850.           quickly as it can. This technique provides the most efficient use of
  11851.           the send
  11852.           queue by your program and by ADSP. Because ADSP does not remove data
  11853.           from the send queue until that data has not only been sent but also
  11854.           acknowledged by the remote connection end, using the flush parameter
  11855.           to the
  11856.           dspWrite routine does not guarantee that the send queue is empty. You
  11857.           can
  11858.           use the dspStatus routine to determine how much free buffer space is
  11859.           available in the send queue. 
  11860.  
  11861.          The dspRead routine reads data from the receive queue into your
  11862.          application’s
  11863.           private data buffer. ADSP does not transmit data until there is space
  11864.           available
  11865.           in the other end’s receive queue to accept it. Because a full receive
  11866.           queue
  11867.           slows the communications rate, you should read data from the receive
  11868.           queue
  11869.           as often as necessary to keep sufficient buffer space available for
  11870.           new data. You
  11871.           can use either of two techniques to do this:
  11872.  
  11873.             •  Allocate a small receive queue (about 600 bytes) and call the
  11874.             dspRead
  11875.                 routine asynchronously. Your completion routine for the dspRead
  11876.                 routine
  11877.                 should then call the dspRead routine again.
  11878.  
  11879.             •  Allocate a large receive queue and call the dspRead routine less
  11880.             frequently.
  11881.  
  11882.            If there is less data in the receive queue than the amount you
  11883.            specify with the
  11884.            reqCount parameter to the dspRead command, the command does not
  11885.            complete execution until there is enough data available to satisfy
  11886.            the request.
  11887.            There are three exceptions to this rule: 
  11888.  
  11889.              •  If the end-of-message bit in the ADSP packet header is set, the
  11890.              dspRead
  11891.                  command reads the data in the receive queue, returns the actual
  11892.                  amount
  11893.                  of data read in the actCount parameter, and returns the eom
  11894.                  parameter set
  11895.                  to 1. 
  11896.  
  11897.              •  If you have closed the connection end before calling the dspRead
  11898.              routine
  11899.                   (that is, the connection is half open), the command reads
  11900.                   whatever data
  11901.                   is available and returns the actual amount of data read in the
  11902.                   actCount
  11903.                  parameter. 
  11904.  
  11905.              •  If ADSP has closed the connection before you call the dspRead
  11906.              routine
  11907.                   and there is no data in the receive queue, the routine returns
  11908.                   the noErr
  11909.                   result code with the actCount parameter set to 0 and the eom
  11910.                   parameter
  11911.                   set to 0.
  11912.  
  11913.            In addition to the byte-stream data format implemented by the dspRead
  11914.            and
  11915.            dspWrite routines, ADSP provides a mechanism for sending and
  11916.            receiving
  11917.            control signals or information separate from the byte stream. You use
  11918.            the
  11919.            dspAttention routine to send an attention code and an attention
  11920.            message to
  11921.            the remote connection end. When your connection end receives an
  11922.            attention
  11923.            message, ADSP’s interrupt handler sets the eAttention flag in the
  11924.            userFlags
  11925.            field of the CCB and calls your user routine. Your user routine must
  11926.            first
  11927.            clear the userFlags field. Then your routine can read the attention
  11928.            code and
  11929.            attention message and take whatever action you deem appropriate. 
  11930.  
  11931.           Because ADSP is often used by terminal emulation programs and other
  11932.           applications that pass the data they receive on to the user without
  11933.           processing
  11934.           it, attention messages provide a mechanism for the applications that
  11935.           are
  11936.           clients of the connection ends to communicate with each other. For
  11937.           example,
  11938.           you could use attention messages to implement a handshaking and
  11939.           data-checking protocol for a program that transfers disk files between
  11940.           two
  11941.           applications, neither one of which is a file server. Or a database
  11942.           server on a
  11943.           mainframe computer that uses ADSP to communicate with Macintosh
  11944.           computer workstations could use the attention mechanism to inform the
  11945.           workstations when the database is about to be closed down for
  11946.           maintenance.
  11947.  
  11948.    8.  When you are ready to close the ADSP connection, you can use the dspClose
  11949.    or
  11950.         dspRemove routines to close the connection end. Use the dspClose routine
  11951.         if
  11952.         you intend to use that connection end to open another connection and do
  11953.         not
  11954.         want to release the memory you allocated for the connection end. Use the
  11955.         dspRemove routine if you are completely finished with the connection end
  11956.         and want to release the memory.
  11957.  
  11958.         You can continue to read data from the receive queue after you have
  11959.         called the
  11960.         dspClose routine, but not after you have called the dspRemove routine.
  11961.         You
  11962.         can use the dspStatus routine to determine whether any data is remaining
  11963.         in
  11964.         the receive queue, or you can read data from the receive queue until
  11965.         both the
  11966.         actCount and eom fields of the dspRead parameter block return 0.
  11967.  
  11968.        If you set the abort parameter for the dspClose or dspRemove routines to
  11969.        0,
  11970.        then ADSP does not close the connection or the connection end until it
  11971.        has
  11972.        sent—and received acknowledgment for—all data in the send queue and any
  11973.        pending attention messages. If you set the abort parameter to 1, then
  11974.        ADSP
  11975.        discards any data in the send queue and any attention messages that have
  11976.        not
  11977.        already been sent.
  11978.  
  11979.         After you have executed the dspRemove routine, you can release the
  11980.         memory
  11981.         you allocated for the CCB and data buffers.
  11982.  
  11983. Listing 32-4 illustrates the use of ADSP. This routine opens the .MPP and .DSP
  11984. drivers and allocates memory for its internal data buffers, for the CCB, and for
  11985. the send, receive, and attention-message buffers. Then the routine uses the
  11986. dspInit routine to establish a connection end and uses NBP to register the name
  11987. of the connection end on the internet. (The user routine specified by the
  11988. userRoutine parameter to the dspInit function is shown in Listing 326.) Next,
  11989. Listing 32-4 uses the dspOptions routine to set the blocking factor to 24 bytes.
  11990. The routine uses NBP to determine the address of a socket whose name was chosen
  11991. by the user and sends an open-connection request (dspOpen) to that socket. When
  11992. the dspOpen routine completes execution, the routine sends data and an attention
  11993. message to the remote connection end and reads data from its receive queue.
  11994. Finally, the routine closes the connection end with the dspRemove routine and
  11995. releases the memory it allocated.  
  11996.  
  11997. ¿ Listing 32-4   Using ADSP to establish and use a connection
  11998.  
  11999. PROCEDURE MyADSP;
  12000.  
  12001. CONST
  12002.    qSize=  600;         {queue space}
  12003.    myDataSize=  128;    {size of internal read/write buffers}
  12004.    blockFact=  24;      {blocking factor}
  12005. TYPE  
  12006. {modify the connection control block to add storage for A5}
  12007.    myTRCCB = RECORD
  12008.       myA5: longint;
  12009.       u: TRCCB;
  12010.    END;
  12011. VAR
  12012.    dspSendQPtr:      Ptr;
  12013.    dspRecvQPtr:      Ptr;
  12014.    dspAttnBufPtr:    Ptr;
  12015.    myData2ReadPtr:   Ptr;
  12016.    myData2WritePtr:  Ptr;
  12017.    myAttnMsgPtr:     Ptr;
  12018.    dspCCB:           myTRCCB;
  12019.    myDSPPBPtr:       DSPPBPtr;
  12020.    myMPPPBPtr:       MPPPBPtr;
  12021.    myNTEName:        NamesTableEntry;
  12022.    myAddrBlk:        AddrBlock;
  12023.    drvrRefNum:       Integer;
  12024.    mppRefNum:        Integer;
  12025.    connRefNum:       Integer;
  12026.    gReceivedAnEvent: Boolean;
  12027.    myAttnCode:       Integer;
  12028.    tempFlag:         Byte;
  12029.    tempCFlag:        Integer;
  12030.    myErr:            OSErr;  
  12031.  
  12032. BEGIN 
  12033.    myErr := OpenDriver('.MPP', mppRefNum);    {open .MPP driver}
  12034.    IF myErr <> noErr THEN DoErr(myErr);       {check and handle error}
  12035.    myErr := OpenDriver('.DSP', drvrRefNum);   {open .DSP driver}
  12036.    IF myErr <> noErr THEN DoErr(myErr);       {check and handle error}
  12037.   
  12038.    {allocate memory for data buffers}
  12039.    dspSendQPtr := NewPtr(qSize);              {ADSP use only}
  12040.    dspRecvQPtr := NewPtr(qSize);              {ADSP use only}
  12041.    dspAttnBufPtr := NewPtr(attnBufSize);      {ADSP use only}
  12042.    myData2ReadPtr := NewPtr(myDataSize);
  12043.    myData2WritePtr := NewPtr(myDataSize);
  12044.    myAttnMsgPtr := NewPtr(myDataSize);
  12045.    myDSPPBPtr := DSPPBPtr(NewPtr(SizeOf(DSPParamBlock)));
  12046.    myMPPPBPtr := MPPPBPtr(NewPtr(SizeOf(MPPParamBlock)));
  12047.   
  12048.    WITH myDSPPBPtr^ DO       {set up dspInit parameters}
  12049.    BEGIN
  12050.       ioCRefNum := drvrRefNum;     {ADSP driver ref num}
  12051.       csCode := dspInit;
  12052.       ccbPtr := @dspCCB;           {pointer to CCB}
  12053.       userRoutine := @myConnectionEvtUserRoutine;
  12054.                                    {see Listing 32-6}
  12055.       sendQSize := qSize;          {size of send queue}
  12056.       sendQueue := dspSendQPtr;    {send-queue buffer}
  12057.       recvQSize := qSize;          {size of receive queue}
  12058.       recvQueue := dspRecvQPtr;    {receive-queue buffer}
  12059.       attnPtr := dspAttnBufPtr;    {receive-attention buffer}
  12060.       localSocket := 0;            {let ADSP assign socket}
  12061.    END;
  12062.  
  12063.    gReceivedAnEvent := FALSE;
  12064.    dspCCB.myA5 := SetCurrentA5;    {save A5 for the user routine}
  12065.    {establish a connection end}
  12066.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12067.    IF myErr <> noErr THEN DoErr(myErr);  {check and handle error}
  12068.    connRefNum := myDSPPBPtr^.ccbRefNum;  {save CCB ref num for later}
  12069.  
  12070.    NBPSetNTE(@myNTEName, 'The Object', 'The Type',
  12071.      '*', myDSPPBPtr^.localSocket);  
  12072.                                          {set up NBP names table entry}
  12073.    WITH myMPPPBPtr^ DO                   {set up PRegisterName }
  12074.                                          { parameters}
  12075.    BEGIN
  12076.       interval := 7;                     {retransmit every 7*8=56 ticks}
  12077.       count := 3;                        {and retry 3 times}
  12078.       entityPtr := @myNTEName;           {name to register}
  12079.       verifyFlag :=   0;                 {don't verify this name}
  12080.    END;
  12081.    {register this socket}
  12082.    myErr := PRegisterName(myMPPPBPtr, FALSE);  
  12083.                                          {register this socket}
  12084.    IF myErr <> noErr THEN DoErr(myErr);  {check and handle error}
  12085.  
  12086.    WITH myDSPPBPtr^ DO                   {set up dspOptions parameters}
  12087.    BEGIN
  12088.       ioCRefNum := drvrRefNum;           {ADSP driver ref num}
  12089.       csCode := dspOptions;
  12090.       ccbRefNum := connRefNum;           {connection ref num}
  12091.       sendBlocking := blockFact;         {quantum for data packet}
  12092.       badSeqMax :=   0:                  {use default}
  12093.       useCheckSum :=   0;                {don't calculate checksum}
  12094.    END;
  12095.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12096.                                          {set options}
  12097.    IF myErr <> noErr THEN DoErr(myErr);  {check and handle error}
  12098.  
  12099.    PickASocket(myAddrBlk);
  12100.       {routine using the PLookupName function to pick a socket }
  12101.       { that will be used to establish an open connection}
  12102.  
  12103.    {open a connection with the chosen socket}
  12104.    WITH myDSPPBPtr^ DO                    {set up dspOpen parameters}
  12105.    BEGIN
  12106.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12107.       csCode := dspOpen;
  12108.       ccbRefNum := connRefNum;            {connection ref num}
  12109.       remoteAddress := myAddrBlk;         {address of remote socket }
  12110.                                           { from PLookupName function}
  12111.       filterAddress := myAddrBlk;         {address filter, specified }
  12112.                                           { socket address only}
  12113.       ocMode := ocRequest;                {open connection mode}
  12114.       ocInterval := 0;                    {use default retry interval}
  12115.       ocMaximum := 0;                     {use default retry maximum}
  12116.    END;
  12117.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12118.                                           {open a connection}
  12119.    IF myErr <> noErr THEN DoErr(myErr);   {check and handle error}
  12120.  
  12121.    {the connection with the chosen socket is open, so now send to }
  12122.    { the send queue exactly myDataSize number of bytes}
  12123.    WITH myDSPPBPtr^ DO                    {set up dspWrite parameters}
  12124.    BEGIN       
  12125.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12126.       csCode := dspWrite;
  12127.       ccbRefNum := connRefNum;            {connection ref num}
  12128.       reqCount := myDataSize;             {write this number of bytes}
  12129.       dataPtr := myData2WritePtr;         {pointer to send queue}
  12130.       eom := 1;                           {1 means last byte is logical }
  12131.                                           { end-of-message}
  12132.       flush := 1;                         {1 means send data now}
  12133.    END;
  12134.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12135.                                           {send data to the remote }
  12136.                                           { connection}
  12137.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12138.  
  12139.    {now send an attention message to the remote connection end}
  12140.    WITH myDSPPBPtr^ DO                    {set up dspAttention parameters}
  12141.    BEGIN
  12142.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12143.       csCode := dspAttention;
  12144.       ccbRefNum := connRefNum;            {connection ref num}
  12145.       attnCode := 0;                      {user-defined attention code}
  12146.       attnSize := myDataSize;             {length of attention message}
  12147.       attnData := myAttnMsgPtr;           {attention message}
  12148.    END;
  12149.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12150.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12151.  
  12152.    {Now read from the receive queue exactly myDataSize number }
  12153.    { of bytes.}
  12154.    WITH myDSPPBPtr^ DO                    {set up dspRead parameters}
  12155.    BEGIN 
  12156.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12157.       csCode := dspRead;
  12158.       ccbRefNum := connRefNum;            {connection ref num}
  12159.       reqCount := myDataSize;             {read this number of bytes}
  12160.       dataPtr := myData2ReadPtr;          {pointer to read buffer}
  12161.    END;
  12162.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12163.                                           {read data from the remote }
  12164.                                           { connection}
  12165.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12166.  
  12167.    {we're done with the connection, so remove it}
  12168.    WITH myDSPPBPtr^ DO                    {set up dspRemove parameters}
  12169.    BEGIN
  12170.       ioCRefNum := drvrRefNum;            {ADSP driver ref num}
  12171.       csCode := dspRemove;
  12172.       ccbRefNum := connRefNum;            {connection ref num}
  12173.       abort := 0;                         {don't close until everything }
  12174.                                           { is sent and received}
  12175.    END;
  12176.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12177.                                           {close and remove the connection}
  12178.    IF myErr <> noErr THEN DOErr(myErr);{check and handle error}
  12179.  
  12180.    {we're done with this connection, so give back the memory}
  12181.    DisposPtr(dspSendQPtr);
  12182.    DisposPtr(dspRecvQPtr);
  12183.    DisposPtr(dspAttnBufPtr);
  12184.    DisposPtr(myData2ReadPtr);
  12185.    DisposPtr(myData2WritePtr);
  12186.    DisposPtr(myAttnMsgPtr);
  12187.    DisposPtr(Ptr(myDSPPBPtr));
  12188.    DisposPtr(Ptr(myMPPPBPtr));
  12189.  
  12190. END;      {MyADSP}
  12191. _______________________________________________________________________________
  12192.  
  12193. æKY Creating…and…Using…a…Connection…Listener
  12194. æC »Creating and Using a Connection Listener                             AppleTalk Manager
  12195. _______________________________________________________________________________
  12196.  
  12197. A connection listener is a special sort of AppleTalk Data Stream Protocol (ADSP)
  12198. connection end that cannot receive or transmit data streams or attention
  12199. messages. The sole function of a connection listener is to wait passively to
  12200. receive an open-connection request and to inform its client, the connection
  12201. server, when it receives one. The connection server can then accept or deny the
  12202. open-connection request. If it accepts the request, the connection server
  12203. selects a socket to use as a connection end, establishes a connection end on
  12204. that socket, and sends an acknowledgment and connection request back to the
  12205. requesting connection end. The connection server can use the same socket as it
  12206. used for the connection listener or can select a different socket as the
  12207. connection end.
  12208.  
  12209. Use the following procedure to establish a connection listener and to use that
  12210. connection listener to open a connection with a remote connection end:
  12211.  
  12212.    1.  Use the MPPOpen function to open the .MPP driver and then use the
  12213.         OpenDriver function to open the .DSP driver. The OpenDriver function
  12214.         returns the reference number for the .DSP driver. You must supply this
  12215.         reference number each time you call the .DSP driver.
  12216.  
  12217.    2.  Allocate nonrelocatable memory for a connection control block (CCB). (The
  12218.         CCB is described in “The ADSP Connection Control Block” earlier in this
  12219.         chapter.) A connection listener does not need send and receive queues or
  12220.         an
  12221.         attention-message buffer. The memory that you allocate becomes the
  12222.         property
  12223.         of ADSP when you call the dspCLInit routine to establish a connection
  12224.         listener.
  12225.         You cannot write any data to this memory except by calling ADSP, and you
  12226.         must ensure that the memory remains locked until you call the dspRemove
  12227.         routine to eliminate the connection end. The CCB is 242 bytes. 
  12228.  
  12229.    3.  Call the dspCLInit routine to establish a connection listener. You must
  12230.    provide
  12231.         a pointer to the CCB. 
  12232.  
  12233.        If there is a specific socket that you want to use for the connection
  12234.        listener, you
  12235.        can specify the socket number in the localSocket parameter. If you want
  12236.        ADSP
  12237.        to assign the socket for you, specify 0 for the localSocket parameter.
  12238.        ADSP
  12239.        returns the socket number when the dspCLInit routine completes execution.
  12240.  
  12241.    4.  If you wish, you can use the NBPRegister function to add the name and
  12242.         address of your connection listener to the node’s names table. The
  12243.         NBPRegister function is described in the AppleTalk Manager chapter of
  12244.         Volume II.
  12245.  
  12246.    5.  Use the dspCLListen routine to cause the connection listener to wait for
  12247.    an
  12248.         open-connection request. Because the dspCLListen routine does not
  12249.         complete
  12250.         execution until it receives a connection request, you should call this
  12251.         routine
  12252.         asynchronously. You can specify a value for the filterAddress parameter
  12253.         to
  12254.         restrict the network number, node ID, or socket number from which you
  12255.         will
  12256.         accept an open-connection request. 
  12257.  
  12258.         When the dspCLListen routine receives an open-connection request that
  12259.         meets the restrictions of the filterAddress parameter, it returns a
  12260.         noErr result
  12261.         code (if you executed the routine asynchronously, it places a noErr
  12262.         result code
  12263.         in the ioResult parameter) and places values in the parameter block for
  12264.         the
  12265.         remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq
  12266.         parameters. 
  12267.  
  12268.    6.  If you want to open the connection, call the dspInit routine to establish
  12269.    a
  12270.         connection end. You can use any available socket on the node for the
  12271.         connection end, including the socket that you used for the connection
  12272.         listener.
  12273.         Because a single socket can have more than one CCB connected with it,
  12274.         the
  12275.         socket can function simultaneously as a connection end and a connection
  12276.         listener. 
  12277.  
  12278.         You can check the address of the remote socket to determine if it meets
  12279.         your
  12280.         criteria for a connection end. Although the filterAddress parameter to
  12281.         the
  12282.         dspCLListen routine provides some screening of socket addresses, it
  12283.         cannot
  12284.         check for network number ranges, for example, or for a specific set of
  12285.         socket
  12286.         numbers. If for some reason you want to deny the connection request,
  12287.         call the
  12288.         dspDeny routine, specifying the CCB of the connection listener in the
  12289.         ccbRefNum parameter. Because the dspCLListen routine completes execution
  12290.         when it receives an open-connection request, you must return to step 5
  12291.         to wait
  12292.         for another connection request.
  12293.  
  12294.    7.  Call the dspOpen routine to open the connection. Specify the value
  12295.    ocAccept
  12296.         for the ocMode parameter and specify in the ccbRefNum parameter the
  12297.         reference number of the CCB for the connection end that you want to use.
  12298.         When you call the dspOpen routine, you must provide the values returned
  12299.         by
  12300.         the dspCLListen routine for the remoteCID, remoteAddress, sendSeq,
  12301.         sendWindow, and attnSendSeq parameters.
  12302.  
  12303.         You can poll the state field in the CCB to determine when the connection
  12304.         is
  12305.         open. Alternatively, you can check the result code for the dspOpen
  12306.         routine
  12307.         when the routine completes execution. If the routine returns the noErr
  12308.         result
  12309.         code, then the connection is open.
  12310.  
  12311.     8.  You can now send and receive data and attention messages over the
  12312.          connection, as described in the preceding section, “Opening and
  12313.          Maintaining
  12314.          an ADSP Connection.” When you are ready to close the connection, you
  12315.          can
  12316.          use the dspClose or dspRemove routines, which are also described in the
  12317.          preceding section.
  12318.  
  12319.    9.  When you are finished using the connection listener, you can use the
  12320.         dspCLRemove routine to eliminate it. Once you have called the
  12321.         dspCLRemove routine, you can release the memory you allocated for the
  12322.         connection listener’s CCB.
  12323.  
  12324. Listing 32-5 illustrates the use of ADSP to establish and use a connection
  12325. listener. It opens the .MPP and .DSP drivers and allocates memory for the CCB.
  12326. Then it uses the dspCLInit routine to establish a connection listener, uses the
  12327. Name-Binding Protocol (NBP) to register the name of the connection end on the
  12328. internet, and uses the dspCLListen routine to wait for a connection request.
  12329. When the routine receives a connection request, it calls the dspOpen routine to
  12330. complete the connection.
  12331.  
  12332. ¿ Listing 32-5   Using ADSP to establish and use a connection listener
  12333.  
  12334. VAR
  12335.    dspCCBPtr:     TPCCB;
  12336.    myDSPPBPtr:    DSPPBPtr;
  12337.    myMPPPBPtr:    MPPPBPtr;
  12338.    myNTEName:     NamesTableEntry;
  12339.    drvrRefNum:    Integer;
  12340.    mppRefNum:     Integer;
  12341.    connRefNum:    Integer;
  12342.    myErr:         OSErr;
  12343.  
  12344. BEGIN 
  12345.    myErr := OpenDriver('.MPP', mppRefNum);   { open .MPP driver }
  12346.    IF myErr <> noErr THEN DoErr(myErr);      {check and handle error}
  12347.    myErr := OpenDriver('.DSP', drvrRefNum);  {open .DSP driver}
  12348.    IF myErr <> noErr THEN DoErr(myErr);      {check and handle error}
  12349.  
  12350.    {allocate memory for data buffers}
  12351.    dspCCBPtr := TPCCB(NewPtr(SizeOf(TRCCB)));
  12352.    myDSPPBPtr := DSPPBPtr(NewPtr(SizeOf(DSPParamBlock)));
  12353.    myMPPPBPtr := MPPPBPtr(NewPtr(SizeOf(MPPParamBlock)));
  12354.  
  12355.    WITH myDSPPBPtr^ DO                     {set up dspCLInit parameters}
  12356.    BEGIN
  12357.       ioCRefNum := drvrRefNum;             {ADSP driver ref num}
  12358.       csCode := dspCLInit;
  12359.       ccbPtr := dspCCBPtr;                 {pointer to CCB}
  12360.       localSocket := 0;                    {local socket number}
  12361.    END;
  12362.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE);
  12363.                                            {establish a connection listener}
  12364.  
  12365.    IF myErr <> noErr THEN DoErr(myErr);    {check and handle error}
  12366.    connRefNum := myDSPPBPtr^.ccbRefNum;    {save CCB ref num for later}
  12367.  
  12368.    NBPSetNTE(@myNTEName, 'The Object', 'The Type',
  12369.              '*', myDSPPBPtr^.localSocket);  
  12370.                                            {set up NBP names table entry}
  12371.    WITH myMPPPBPtr^ DO                     {set up PRegisterName parameters}
  12372.    BEGIN
  12373.       interval := 7;                       {retransmit every 7*8=56 ticks}
  12374.       count := 3;                          {and retry 3 times}
  12375.       entityPtr := @myNTEname;             {name to register}
  12376.       verifyFlag := 0;                     {don't verify this name}
  12377.    END;
  12378.    myErr := PRegisterName(myMPPPBPtr, FALSE);
  12379.                                            {register this name}
  12380.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12381.  
  12382.    WITH myDSPPBPtr^ DO                     {set up dspCLListen parameters}
  12383.    BEGIN
  12384.       ioCRefNum := drvrRefNum;             {ADSP driver ref num}
  12385.       csCode := dspCLListen;
  12386.       ccbRefNum := connRefNum;             {connection ref num}
  12387.       filterAddress := AddrBlock(0);       {connect with anybody}
  12388.    END;
  12389.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), TRUE);
  12390.                                            {listen for connection requests}
  12391.    WHILE myDSPPBPtr^.ioResult = 1 DO
  12392.    BEGIN
  12393.       {return control to user while waiting for }
  12394.       { a connection request}
  12395.       GoDoSomething;
  12396.    END;
  12397.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12398.  
  12399.    {You received a connection request; now open a connection }
  12400.    { The dspCLListen call has returned values into the }
  12401.    { remoteCID, remoteAddress, sendSeq, sendWindow, }
  12402.    { and attnSendSeq fields of the parameter block.}
  12403.  
  12404.    WITH myDSPPBPtr^ DO                      {set up dspOpen parameters}
  12405.    BEGIN
  12406.       ioCRefNum := drvrRefNum;              {ADSP driver ref num}
  12407.       csCode := dspOpen;
  12408.       ccbRefNum := connRefNum;              {connection ref num}
  12409.       ocMode := ocAccept;                   {open connection mode}
  12410.       ocInterval := 0;                      {use default retry interval}
  12411.       ocMaximum := 0;                       {use default retry maximum}
  12412.    END;
  12413.    myErr := PBControl(ParmBlkPtr(myDSPPBPtr), FALSE); 
  12414.                                             {open a connection}
  12415.    IF myErr <> noErr THEN DoErr(myErr);{check and handle error}
  12416.  
  12417.  
  12418.    {Listing 32-4 shows how to use ADSP to maintain a connection.}
  12419.   
  12420. END;      {MyCLADSP}
  12421.  
  12422. _______________________________________________________________________________
  12423.  
  12424. æKY Writing…a…User…Routine…for…Connection…Events
  12425. æC »Writing a User Routine for Connection Events                         AppleTalk Manager
  12426. _______________________________________________________________________________
  12427.  
  12428. When you execute the dspInit routine, you can specify a pointer to a routine
  12429. that you provide (referred to as the user routine ). Whenever an unsolicited
  12430. connection event occurs, the AppleTalk Data Stream Protocol (ADSP) sets a flag
  12431. in the connection control block (CCB) and calls the user routine. The user
  12432. routine must clear the flag to acknowledge that it has read the flag field, and
  12433. then can respond to the event in any manner you deem appropriate. The CCB flags
  12434. are described in “The ADSP Connection Control Block” earlier in this chapter.
  12435. The four following types of unsolicited connection events set flags in the CCB:
  12436.  
  12437.   •  ADSP has been informed by the remote connection end that the remote
  12438.       connection end is about to close the connection. An appropriate reponse
  12439.       might
  12440.       be to store a flag indicating that the connection end is about to close.
  12441.       When your
  12442.       application regains control, it can then display a dialog box informing
  12443.       the user
  12444.       of this event and asking whether the application should attempt to
  12445.       reconnect
  12446.       later.  
  12447.  
  12448.   •  ADSP has determined that the remote connection end is not responding and so
  12449.       has closed the connection. Your user routine can attempt to open a new
  12450.       connection immediately. Alternatively, you can store a flag indicating
  12451.       that the
  12452.       connection has closed, and when your application regains control, it can
  12453.       display
  12454.       a dialog box asking the user whether to attempt to reconnect. 
  12455.  
  12456.   •  ADSP has received an attention message from the remote connection end.
  12457.       Depending on what you are using the attention-message mechanism for, you
  12458.       might want to read the attention code in the attnCode field of the CCB and
  12459.       the
  12460.       attention message pointed to by the attnPtr field of the CCB. 
  12461.  
  12462.   •  ADSP has received a forward reset command from the remote client end, has
  12463.       discarded all ADSP data not yet delivered, including the data in the
  12464.       receive
  12465.       queue of the local client end, and has resynchronized the connection. Your
  12466.       response to this event depends on the purpose for which you are using the
  12467.       forward reset mechanism. You might want to resend the last data you have
  12468.       sent
  12469.       or inform the user of the event. 
  12470.  
  12471. When ADSP calls your user routine, the CPU is in interrupt-processing mode and
  12472. register A1 contains a pointer to the CCB of the connection end that generated
  12473. the event. You can examine the userFlags field of the CCB to determine what
  12474. event caused the interrupt, and you can examine the state field of the CCB to
  12475. determine the current state of the connection. 
  12476.  
  12477. Because the CPU is set to interrupt-processing mode, your user routine must
  12478. preserve all registers other than A0, A1, D0, D1, and D2. Your routine must not
  12479. make any direct or indirect calls to the Memory Manager and can’t depend on
  12480. handles to unlocked blocks being valid. If you want to use any of your
  12481. application’s global variables, you must save the contents of the A5 register
  12482. before using the variables, and you must restore the A5 register before your
  12483. routine terminates. Listings 32-4 and 32-6 illustrate the use of the CCB to
  12484. store the pointer to your application’s global variables. 
  12485.  
  12486. If you want to execute a routine each time an unsolicited connection event
  12487. occurs but the interrupt environment is too restrictive, you can specify a NIL
  12488. pointer to the user routine and periodically poll the userFlags field of the
  12489. CCB. 
  12490.  
  12491.     † Warning:  When an unsolicited connection event occurs, you must clear the
  12492.         bit in the userFlags field to 0 or the connection will hang. To ensure
  12493.         that you
  12494.        do not lose any attention messages, you must read any attention messages
  12495.        into
  12496.        an internal buffer before you clear the bit in the userFlags field.  Ê 
  12497.  
  12498. Listing 32-6 is the user routine called by Listing 32-4. When this routine is
  12499. called, it first checks the CCB to determine the source of the interrupt and
  12500. then clears the bit in the userFlags field of the CCB. If the routine has
  12501. received an attention message, the user routine reads the message into an
  12502. internal buffer before it clears the flag bit. The definitions of procedures
  12503. PushA5, GetMyTRCCBA5, and PopA5 are shown in Listing 32-6 for your convenience.
  12504. In a complete application these procedures would be defined in the calling
  12505. routine (Listing 32-4).
  12506.  
  12507. ¿ Listing 32-6   An ADSP user routine 
  12508.  
  12509. PROCEDURE PushA5;             {moves current value of A5 onto stack}
  12510.    INLINE $2F0D;              {MOVE.L A5,-(SP)}
  12511.   
  12512. PROCEDURE GetMyTRCCBA5;       {Retrieves A5 from the head of the TRCCB }
  12513.                               { (pointed to by A1) and sticks it in A5.}
  12514.    INLINE $2A69, $FFFC; {MOVE.L -4(A1), A5}
  12515.  
  12516. PROCEDURE PopA5;              {restores A5 from stack}
  12517.    INLINE $2A5F;              {MOVE.L (SP)+, A5}
  12518.  
  12519. PROCEDURE myConnectionEvtUserRoutine;
  12520.  
  12521. BEGIN
  12522. {The connection received an unexpected connection event.  Find out }
  12523. { what kind and process accordingly.}
  12524.   
  12525.    PushA5;                    {save the current A5}
  12526.    GetMyTRCCBA5;              {set up A5 to point to your application's }
  12527.                               { global variables}
  12528.   
  12529.    WITH dspCCB.u DO
  12530.    BEGIN
  12531.       IF BAND(userFlags, eClosed) <> 0 THEN TellUserItsClosed;
  12532.       IF BAND(userFlags, eTearDown) <> 0 THEN TellUserItsBroken;
  12533.       IF BAND(userFlags, eFwdReset) <> 0 THEN TellUserItsReset;
  12534.       IF BAND(userFlags, eAttention) <> 0 THEN
  12535.       BEGIN      {the event is an attention message}
  12536.          myAttnCode := AttnCode;          {Get the attention code.}
  12537.          CopyAttnMsg(AttnPtr, AttnSize, @myAttnData);
  12538.                               {copy the attention }
  12539.                               { message into our buffer}
  12540.          tempFlag := userFlags;
  12541.          tempCFlag := eAttention;
  12542.          BClr(LongInt(tempFlag), tempCFlag);  {clear the flag}
  12543.          userFlags := tempFlag;
  12544.          {do something with the message}
  12545.       END;
  12546.       gReceivedAnEvent := TRUE;
  12547.    END;
  12548.    PopA5;                                  {restore the current A5}
  12549. END;
  12550.  
  12551. _______________________________________________________________________________
  12552.  
  12553. æKY .DSP…Driver…Routines
  12554. æC ».DSP Driver Routines                                                 AppleTalk Manager
  12555. _______________________________________________________________________________
  12556.  
  12557. The .DSP driver implements the AppleTalk Data Stream Protocol (ADSP). You send
  12558. commands to ADSP and obtain information about ADSP by executing the .DSP driver
  12559. routines described in this section. Each routine is implemented as a call to the
  12560. Device Manager’s PBControl function, as follows:
  12561.  
  12562. FUNCTION PBControl (paramBlock: ParmBlkPtr; async: BOOLEAN) : OSErr;
  12563.  
  12564. The paramBlock parameter is a pointer to the parameter block used by the
  12565. PBControl function for .DSP routines, and the async parameter is a Boolean that
  12566. specifies whether the function is to execute synchronously or asynchronously.
  12567. Set the async parameter to TRUE to execute the function asynchronously.
  12568.  
  12569. The parameter block is shown in “The .DSP Parameter Block” earlier in this
  12570. chapter. The parameters used with each function are described in this section. 
  12571.  
  12572. For a general discussion of the use of ADSP, see “Using ADSP” earlier in this
  12573. chapter.
  12574.  
  12575. _______________________________________________________________________________
  12576.  
  12577. æKY Establishing…&…Terminating…an…ADSP…Connection
  12578. æC »Establishing & Terminating an ADSP Connection                        AppleTalk Manager
  12579. _______________________________________________________________________________
  12580.  
  12581. You can use the routines described in this section to 
  12582.  
  12583.   •  establish a connection end
  12584.  
  12585.   •  set the values for parameters that control the behavior of a connection end
  12586.  
  12587.   •  open a connection
  12588.  
  12589.   •  assign an identification number to a connection end
  12590.  
  12591.   •  close a connection end
  12592.  
  12593.   •  eliminate a connection end
  12594.  
  12595. dspInit
  12596.  
  12597.    Parameter block
  12598.          ¨      16      ioResult              word        result code 
  12599.          Æ      24      ioCRefNum       word        driver reference number
  12600.          Æ      26      csCode                 word         always dspInit
  12601.          ¨      32      ccbRefNum        word        reference number of CCB
  12602.          Æ      34      ccbPtr                    long         pointer to CCB
  12603.          Æ      38      userRoutine       long         pointer to routine to
  12604.          call on 
  12605.  
  12606.  
  12607.  
  12608.          Æ      42      sendQSize           word        size in bytes of the
  12609.          send queue
  12610.          Æ      44      sendQueue          long        pointer to send queue
  12611.          Æ      48      recvQSize            word       size in bytes of the
  12612.          receive queue
  12613.          Æ      50      recvQueue           long       pointer to receive queue
  12614.          Æ      54      attnPtr                   long       pointer to buffer
  12615.          for incoming 
  12616.  
  12617.  
  12618.  
  12619.          ´      58      localSocket  byte  DDP      socket number for this 
  12620.  
  12621.                                                                           end
  12622.  
  12623. The dspInit routine establishes a connection end; that is, it assigns a specific
  12624. socket for use by ADSP and initializes the variables that ADSP uses to maintain
  12625. the connection. The dspInit routine does not open the connection end or
  12626. establish a connection with a remote connection end; you must follow the dspInit
  12627. routine with the dspOpen routine to perform those tasks. Use the dspCLInit
  12628. routine to establish a connection listener. Use the dspRemove routine to
  12629. eliminate a connection end.
  12630.  
  12631. When you send bytes to a remote connection end, ADSP stores the bytes in a
  12632. buffer called the send queue . Until the remote connection end acknowledges
  12633. their receipt, ADSP keeps the bytes you sent in the send queue so that they are
  12634. available to be retransmitted if necessary. When the local connection end
  12635. receives bytes, it stores them in a buffer called the receive queue  until you
  12636. read them. 
  12637.  
  12638. You must allocate memory for the send and receive queues and for a buffer that
  12639. holds incoming attention messages. You must also allocate a nonrelocatable block
  12640. of memory for the CCB for this connection end. 
  12641.  
  12642.    Note:  When you call the dspInit routine, the memory that you allocate
  12643.    becomes
  12644.    the property of ADSP. You cannot write any data to this memory except by
  12645.    calling ADSP routines, and you must ensure that the memory remains
  12646.    locked until you call the dspRemove routine to eliminate the connection
  12647.    end. 
  12648.  
  12649. Fields
  12650.  
  12651. ioResult                         The result of the routine. When you execute the
  12652. routine
  12653.                                          asynchronously, the routine sets this
  12654.                                          parameter to 1 and
  12655.                                          returns a routine result of noErr as
  12656.                                          soon as the routine
  12657.                                          begins execution. When the routine
  12658.                                          completes execution, it
  12659.                                          sets the ioResult parameter to the
  12660.                                          actual result code. 
  12661.  
  12662. ioCRefNum                  The driver reference number. This parameter is
  12663. returned by
  12664.                                           the OpenDriver function. You must
  12665.                                           specify this number
  12666.                                           every time you call the .DSP driver. 
  12667.  
  12668. csCode                            The routine selector, always equal to dspInit
  12669. for this routine.
  12670.  
  12671. ccbRefNum                   The CCB reference number. The dspInit routine
  12672. returns this
  12673.                                           number. You must provide this number
  12674.                                           in all subsequent
  12675.                                           calls to this connection end.
  12676.  
  12677. ccbPtr                               A pointer to the CCB that you allocated.
  12678. The CCB is 242 bytes
  12679.                                           in size and is described in “The ADSP
  12680.                                           Connection Control
  12681.                                           Block” earlier in this chapter.
  12682.  
  12683. userRoutine                   A pointer to a routine that is to be called each
  12684. time the
  12685.                                           connection end receives an unsolicited
  12686.                                           connection event.
  12687.                                           Specify NIL for this parameter if you
  12688.                                           do not want to supply a
  12689.                                           user routine. Connection events and
  12690.                                           user routines are
  12691.                                           discussed in “Writing a User Routine
  12692.                                           for Connection
  12693.                                           Events” earlier in this chapter.
  12694.  
  12695. sendQSize                     The size in bytes of the send queue. A queue size
  12696. of 600 bytes
  12697.                                          should work well for most applications.
  12698.                                          If you are using
  12699.                                          ADSP to send a continuous flow of data,
  12700.                                          a larger data buffer
  12701.                                          improves performance. If your
  12702.                                          application is sending the
  12703.                                          user’s keystrokes, a smaller buffer
  12704.                                          should be adequate. The
  12705.                                          constant minDSPQueueSize indicates the
  12706.                                          minimum queue
  12707.                                          size that you can use.
  12708.  
  12709. sendQueue                   A pointer to the send queue that you allocated. 
  12710.  
  12711. recvQSize                     The size in bytes of the receive queue. A queue
  12712. size of 600
  12713.                                         bytes should work well for most
  12714.                                         applications. If you are using
  12715.                                         ADSP to receive a continuous flow of
  12716.                                         data, a larger data
  12717.                                         buffer improves performance. If your
  12718.                                         application is receiving
  12719.                                         a user’s keystrokes, a smaller buffer
  12720.                                         should be adequate. The
  12721.                                         constant minDSPQueueSize indicates the
  12722.                                         minimum queue
  12723.                                         size that you can use.
  12724.  
  12725. recvQueue                   A pointer to the receive queue that you allocated.
  12726.  
  12727. attnPtr                           A pointer to the attention-message buffer that
  12728. you allocated.
  12729.                                         The attention-message buffer must be the
  12730.                                         size of the constant
  12731.                                          attnBufSize.
  12732.  
  12733. localSocket                   The DDP socket number of the socket that you want
  12734. ADSP to
  12735.                                         use for this connection end. Specify 0
  12736.                                         for this parameter to
  12737.                                         cause ADSP to assign the socket. In the
  12738.                                         latter case, ADSP
  12739.                                         returns the socket number when the
  12740.                                         dspInit routine
  12741.                                         completes execution.
  12742.  
  12743.    Result codes
  12744.           noErr                                 0        No error
  12745.           ddpSktErr                      –91       Error opening socket
  12746.           errDSPQueueSize    –1274       Send or receive queue is too small
  12747.  
  12748.  dspOptions 
  12749.  
  12750.    Parameter block
  12751.         ¨       16      ioResult               word            result code 
  12752.         Æ       24      ioCRefNum        word            driver reference
  12753.         number
  12754.         Æ       26      csCode                  word            always
  12755.         dspOptions
  12756.         Æ       32      ccbRefNum         word           reference number of CCB
  12757.         Æ       34      sendBlocking      word           send-blocking threshold
  12758.         Æ       38      badSeqMax           byte             threshold to send
  12759.         retransmit advice
  12760.         Æ       39      useCheckSum     byte             use DDP checksum?
  12761.  
  12762. The dspOptions routine allows you to set values for several parameters that
  12763. affect the behavior of the local connection end. You can set the options for any
  12764. established connection end, whether open or not.
  12765.  
  12766. Fields
  12767.  
  12768. ioResult                           The result of the routine. When you execute
  12769. the routine
  12770.                                            asynchronously, the routine sets this
  12771.                                            parameter to 1 and
  12772.                                            returns a routine result of noErr as
  12773.                                            soon as the routine
  12774.                                            begins execution. When the routine
  12775.                                            completes execution, it
  12776.                                            sets the ioResult parameter to the
  12777.                                            actual result code. 
  12778.  
  12779. ioCRefNum                   The driver reference number. This parameter is
  12780. returned by
  12781.                                           the OpenDriver function. You must
  12782.                                           specify this number
  12783.                                           every time you call the .DSP driver. 
  12784.  
  12785. csCode                             The routine selector, always equal to
  12786. dspOptions for this
  12787.                                           routine.
  12788.  
  12789. ccbRefNum                    The CCB reference number that was returned by the
  12790. dspInit
  12791.                                           routine.
  12792.  
  12793. sendBlocking                 The maximum number of bytes that may accumulate in
  12794. the
  12795.                                           send queue before ADSP sends a packet
  12796.                                           to the remote
  12797.                                           connection end. ADSP sends a packet
  12798.                                           before the maximum
  12799.                                           number of bytes accumulates if the
  12800.                                           period specified by the
  12801.                                           send timer expires, if you execute the
  12802.                                           dspWrite routine with
  12803.                                           the flush parameter set to 1, or if a
  12804.                                           connection event
  12805.                                           requires that the local connection end
  12806.                                           send an
  12807.                                           acknowledgment packet to the remote
  12808.                                           connection end.
  12809.  
  12810.                                          You can set the sendBlocking parameter
  12811.                                          to any value from 1
  12812.                                          byte to the maximum size of a packet
  12813.                                          (572 bytes). If you set
  12814.                                          the sendBlocking parameter to 0, the
  12815.                                          current value for this
  12816.                                          parameter is not changed. The default
  12817.                                          value for the
  12818.                                          sendBlocking parameter is 16 bytes.
  12819.  
  12820. badSeqMax                   The maximum number of out-of-sequence data packets
  12821. that
  12822.                                         the local connection end can receive
  12823.                                         before requesting the
  12824.                                         remote connection end to retransmit the
  12825.                                         missing data.
  12826.                                         Because a connection end does not
  12827.                                         acknowledge the receipt of
  12828.                                         a data packet received out of sequence,
  12829.                                         the  retransmit timer
  12830.                                         of the remote connection end will expire
  12831.                                         eventually and the
  12832.                                         connection end will retransmit the data.
  12833.                                         The badSeqMax
  12834.                                         parameter allows you to cause the data
  12835.                                         to be retransmitted
  12836.                                         before the retransmit timer of the
  12837.                                         remote connection end has
  12838.                                         expired.
  12839.  
  12840.                                         You can set the badSeqMax parameter to
  12841.                                         any value from 1 to
  12842.                                         255. If you set the badSeqMax parameter
  12843.                                         to 0, the current
  12844.                                         value for this parameter is not changed.
  12845.                                         The default value for
  12846.                                         the badSeqMax parameter is 3.
  12847.  
  12848. useCheckSum             A flag specifying whether DDP should compute a checksum
  12849.                                         and include it in each packet that it
  12850.                                         sends to the remote
  12851.                                         connection end. Set this parameter to 1
  12852.                                         if you want DDP to
  12853.                                         use checksums or to 0 if you do not want
  12854.                                         DDP to use
  12855.                                         checksums. The default value for
  12856.                                         useCheckSum is 0.
  12857.  
  12858.                                         ADSP cannot include a checksum in a
  12859.                                         packet that has a short
  12860.                                         DDP header; that is, a packet being sent
  12861.                                         over LocalTalk to a
  12862.                                         remote socket that is on the same cable
  12863.                                         as the local socket.
  12864.                                         Note that the useCheckSum parameter
  12865.                                         affects only whether
  12866.                                         ADSP includes a checksum in a packet
  12867.                                         that it is sending. If
  12868.                                         ADSP receives a packet that includes a
  12869.                                         checksum, it validates
  12870.                                         the checksum regardless of the setting
  12871.                                         of the useCheckSum
  12872.                                         parameter. 
  12873.  
  12874. Result codes
  12875.         noErr                            0        No error
  12876.         errRefNum        –1280        Bad connection reference number
  12877. _______________________________________________________________________________
  12878.  
  12879. æKY Establishing…&…Terminating…an…ADSP…Connection…(cont'd)
  12880. æC »Establishing & Terminating an ADSP Connection (cont'd)               AppleTalk Manager
  12881. _______________________________________________________________________________
  12882.  
  12883. dspOpen
  12884.  
  12885. Parameter block
  12886.        ¨        16        ioResult                 word        result code 
  12887.        Æ        24        ioCRefNum          word        driver reference number
  12888.        Æ        26        csCode                    word        always dspOpen
  12889.        Æ        32        ccbRefNum           word        reference number of
  12890.        CCB
  12891.        ¨        34        localCID                 word        ID of this
  12892.        connection end
  12893.        ´        36        remoteCID             word       ID of remote
  12894.        connection end
  12895.        ´        38        remoteAddress     long         remote internet address
  12896.        Æ        42        filterAddress         long         filter for open
  12897.        connection requests
  12898.        ´        46        sendSeq                  long         initial send
  12899.        sequence number
  12900.        ´        50        sendWindow        word       initial size of remote
  12901.        receive queue
  12902.        Æ        52        recvSeq                   long        initial receive
  12903.        sequence number
  12904.        ´        56        attnSendSeq          long         attention send
  12905.        sequence number
  12906.        Æ        60        attnRecvSeq          long         attention receive
  12907.        sequence number
  12908.        Æ        64        ocMode                   byte
  12909.        connection-opening mode
  12910.        Æ        65        ocInterval               byte         interval between
  12911.        open requests
  12912.        Æ        66        ocMaximum          byte         retries of
  12913.        open-connection request
  12914.  
  12915. You use the ocMode field of the parameter block to specify the opening mode that
  12916. the dspOpen routine is to use. The dspOpen routine puts a connection end into
  12917. one of the four following opening modes: 
  12918.  
  12919.   •  The ocRequest mode, in which ADSP attempts to open a connection with the
  12920.        socket at the internet address you specify with the remoteAddress
  12921.        parameter. If
  12922.        the socket you specify as a remote address is a connection listener, it
  12923.        is possible
  12924.        that your application will receive a connection acknowledgment and
  12925.        request
  12926.        from a different address than the one to which you sent the
  12927.        open-connection
  12928.        request. You can use the filterAddress parameter to restrict the
  12929.        addresses with
  12930.        which you will accept a connection. 
  12931.  
  12932.        The dspOpen routine completes execution in the ocRequest mode when one of
  12933.         the following occurs: ADSP establishes a connection, your connection end
  12934.         receives a connection denial from the remote connection end, your
  12935.         connection
  12936.         end denies the connection request returned by a connection listener, or
  12937.         ADSP
  12938.         cannot complete the connection within the maximum number of retries that
  12939.         you specified with the ocMaximum parameter.
  12940.  
  12941.   •  The ocPassive mode, in which the connection end waits to receive an
  12942.        open-connection request from a remote connection end. You can use the
  12943.        filterAddress parameter to restrict the addresses from which you will
  12944.        accept a
  12945.        connection request.
  12946.  
  12947.        The dspOpen routine completes execution in the ocPassive mode when ADSP
  12948.        establishes a connection or when either connection end receives a
  12949.        connection
  12950.        denial.
  12951.  
  12952.   •  The ocAccept mode, used by connection servers to complete an
  12953.       open-connection dialog. When a connection server is informed by its
  12954.       connection listener that the connection listener has received an
  12955.       open-connection request, the connection server calls the dspInit routine
  12956.       to
  12957.       establish a connection end and then calls the dspOpen routine in ocAccept
  12958.       mode to complete the connection. You must obtain the following parameters
  12959.       from the dspCLListen routine and provide them to the dspOpen routine:
  12960.       remoteAddress, remoteCID, sendSeq, sendWindow, and attnSendSeq.
  12961.       Connection listeners and connection servers are described in “Creating and
  12962.       Using a Connection Listener,” earlier in this chapter, and in
  12963.       “Establishing and
  12964.       Terminating an ADSP Connection ,” later in this chapter.
  12965.  
  12966.       The dspOpen routine completes execution in the ocAccept mode when ADSP
  12967.       establishes a connection or when either connection end receives a
  12968.       connection
  12969.       denial.
  12970.  
  12971.   •  The ocEstablish mode, in which ADSP considers the connection end
  12972.   established
  12973.       and the connection state open. This mode is for use by clients that
  12974.       determine
  12975.       their connection-opening parameters without using ADSP or the .DSP driver
  12976.       to
  12977.       do so. 
  12978.  
  12979.       You must first use the dspInit routine to establish a connection end and
  12980.       then
  12981.       execute the dspNewCID routine to obtain an identification number (ID) for
  12982.       the
  12983.       local connection end. You must then communicate with the remote connection
  12984.       end to send it the local connection ID and to determine the values of the
  12985.       following parameters: remoteAddress, remoteCID, sendSeq, sendWindow,
  12986.       recvSeq, attnSendSeq, and attnRecvSeq. Only then can you execute the
  12987.       dspOpen
  12988.       routine in the ocEstablish mode.
  12989.  
  12990.       The dspOpen routine completes execution in the ocEstablish mode
  12991.       immediately. 
  12992.  
  12993.        The use of parameters by the dspOpen routine depends on the mode in which
  12994.         the routine is executed, as follows:
  12995.  
  12996. ocRequest                  ocPassive                   ocAccept                
  12997. ocEstablish
  12998.  
  12999. ¨ ioResult                 ¨   ioResult               ¨   ioResult             
  13000. ¨   ioResult
  13001. Æ  ioCRefNum         Æ   ioCRefNum       Æ   ioCRefNum        Æ   ioCRefNum  
  13002. Æ  csCode                   Æ   csCode                  Æ   csCode             
  13003. Æ   csCode
  13004. Æ  ccbRefNum          Æ   ccbRefNum        Æ    ccbRefNum        Æ   ccbRefNum
  13005. ¨  localCID                ¨   localCID               ¨   localCID             
  13006. —  localCID
  13007. ¨  remoteCID           ¨   remoteCID           Æ   remoteCID           Æ
  13008. remoteCID
  13009. Æ  remoteAddress   ¨   remoteAddress   Æ   remoteAddress   Æ  remoteAddress
  13010. Æ  filterAddress        Æ   filterAddress       —  filterAddress       —
  13011. filterAddress
  13012. ¨  sendSeq                 ¨   sendSeq                Æ   sendSeq              
  13013. Æ   sendSeq
  13014. ¨  sendWindow       ¨   sendWindow     Æ   sendWindow       Æ   sendWindow
  13015. — recvSeq                 —  recvSeq                 —  recvSeq                
  13016. Æ   recvSeq
  13017. ¨  attnSendSeq         ¨   attnSendSeq        Æ   attnSendSeq         Æ
  13018. attnSendSeq
  13019. — attnRecvSeq        —  attnRecvSeq         —  attnRecvSeq        Æ
  13020. attnRecvSeq
  13021. Æ  ocMode                 Æ   ocMode                  Æ   ocMode               
  13022. Æ   ocMode
  13023. Æ  ocInterval             Æ   ocInterval             Æ   ocInterval            —
  13024. ocInterval
  13025. Æ  ocMaximum        Æ   ocMaximum        Æ   ocMaximum       —  ocMaximum
  13026.  
  13027. Key:  Æ input    ¨ output    — not used
  13028.  
  13029. Fields
  13030.  
  13031. ioResult                     The result of the routine. When you execute the
  13032. routine
  13033.                                      asynchronously, the routine sets this
  13034.                                      parameter to 1 and
  13035.                                      returns a routine result of noErr as soon
  13036.                                      as the routine begins
  13037.                                      execution. When the routine completes
  13038.                                      execution, it sets the
  13039.                                      ioResult parameter to the actual result
  13040.                                      code. 
  13041.  
  13042. ioCRefNum             The driver reference number. This parameter is returned by
  13043. the
  13044.                                     OpenDriver function. You must specify this
  13045.                                     number every time
  13046.                                      you call the .DSP driver. 
  13047.  
  13048. csCode                       The routine selector, always equal to dspOpen for
  13049. this routine. 
  13050.  
  13051. ccbRefNum              The CCB reference number that was returned by the dspInit
  13052.                                     routine for the connection end that you want
  13053.                                     to use.
  13054.  
  13055. localCID                     The identification number of the local connection
  13056. end. This
  13057.                                      number is assigned by ADSP when the
  13058.                                      connection is opened.
  13059.                                      ADSP includes this number in every packet
  13060.                                      sent to a remote
  13061.                                      connection end. Before you call the dspOpen
  13062.                                      routine in
  13063.                                      ocEstablish mode, you must call the
  13064.                                      dspNewCID routine to
  13065.                                      cause ADSP to assign this value.
  13066.  
  13067. remoteCID               The identification number of the remote connection end.
  13068. This
  13069.                                     parameter is returned by the dspOpen routine
  13070.                                     in the ocRequest
  13071.                                     and ocPassive modes. A connection server
  13072.                                     must provide this
  13073.                                     number to the dspOpen routine when the
  13074.                                     server executes the
  13075.                                     routine in ocAccept mode; in this case, the
  13076.                                     connection server
  13077.                                     obtains the remoteCID value from the
  13078.                                     dspCLListen routine.
  13079.                                     You must provide the remoteCID value to the
  13080.                                     dspOpen routine
  13081.                                     when you use the routine in ocEstablish
  13082.                                     mode. 
  13083.  
  13084. remoteAddress       The internet address of the remote socket with which you
  13085. wish
  13086.                                    to establish communications. This address
  13087.                                    consists of a 2-byte
  13088.                                    network number, a 1-byte node ID, and a
  13089.                                    1-byte socket number.
  13090.                                    You must provide this parameter when you call
  13091.                                    the dspOpen
  13092.                                    routine in the ocRequest or ocEstablish
  13093.                                    modes. This parameter
  13094.                                    is returned by the dspOpen routine when you
  13095.                                    call the routine in
  13096.                                    the ocPassive mode. When you call the dspOpen
  13097.                                    routine in the
  13098.                                    ocAccept mode, you must use the value for the
  13099.                                    remoteAddress
  13100.                                    parameter that was returned by the
  13101.                                    dspCLListen routine. 
  13102.  
  13103. filterAddress           The internet address of the socket from which you will
  13104. accept a
  13105.                                    connection request. The address consists of
  13106.                                    three fields: a 2-byte
  13107.                                    network number, a 1-byte node ID, and a
  13108.                                    1-byte socket number.
  13109.                                    Specify 0 for any of these fields for which
  13110.                                    you wish to impose no
  13111.                                    restrictions. If you specify a filter address
  13112.                                    of $00082500, for
  13113.                                    example, the connection end accepts a
  13114.                                    connection request from
  13115.                                    any socket at node $25 of network $0008. Set
  13116.                                    the filterAddress
  13117.                                    parameter equal to the remoteAddress
  13118.                                    parameter to accept a
  13119.                                    connection only with the socket to which you
  13120.                                    sent a connection
  13121.                                    request.
  13122.  
  13123.                                    When you execute the dspOpen routine in the
  13124.                                    ocPassive mode,
  13125.                                    you can receive a connection request from any
  13126.                                    ADSP
  13127.                                    connection end on the internet. When you
  13128.                                    execute the dspOpen
  13129.                                    routine in the ocRequest mode, your
  13130.                                    connection end can
  13131.                                    receive a connection request acknowledgment
  13132.                                    from an address
  13133.                                    different from the one you specified in the
  13134.                                    remoteAddress
  13135.                                    parameter only if the remote address you
  13136.                                    specified was that of a
  13137.                                    connection listener. In either case, you can
  13138.                                    use the filterAddress
  13139.                                    parameter to avoid acknowledging unwanted
  13140.                                    connection
  13141.                                    requests. 
  13142.  
  13143.                                   When you execute the dspOpen routine in the
  13144.                                   ocAccept mode,
  13145.                                    your connection listener has already received
  13146.                                    and decided to
  13147.                                    accept the connection request. You can
  13148.                                    specify a filter address for
  13149.                                    a connection listener with the dspCLListen
  13150.                                    routine. A
  13151.                                    connection server can use the dspCLDeny
  13152.                                    routine to deny a
  13153.                                    connection request that was accepted by its
  13154.                                    connection listener.
  13155.  
  13156.                                    You cannot use the filter address when you
  13157.                                    execute the dspOpen
  13158.                                    routine in ocEstablish mode.
  13159.  
  13160. sendSeq                    The sequence number of the first byte that the local
  13161. connection
  13162.                                    end will send to the remote connection end.
  13163.                                    ADSP uses this
  13164.                                    number to coordinate communications and to
  13165.                                    check for errors.
  13166.                                    ADSP returns a value for the sendSeq
  13167.                                    parameter when you
  13168.                                    execute the dspOpen routine in the ocRequest
  13169.                                    or ocPassive
  13170.                                    modes. When you execute the dspOpen routine
  13171.                                    in the ocAccept
  13172.                                    mode, you must specify the value for the
  13173.                                    sendSeq parameter
  13174.                                    that was returned by the dspCLListen routine.
  13175.                                    You must
  13176.                                    provide the value for this parameter when you
  13177.                                    execute the
  13178.                                    dspOpen routine in the ocEstablish mode.
  13179.  
  13180. sendWindow         The sequence number of the last byte that the remote
  13181. connection
  13182.                                   end has buffer space to receive. ADSP uses
  13183.                                   this number to
  13184.                                   coordinate communications and to check for
  13185.                                   errors. ADSP
  13186.                                   returns a value for the sendWindow parameter
  13187.                                   when you
  13188.                                   execute the dspOpen routine in the ocRequest
  13189.                                   or ocPassive
  13190.                                   modes. When you execute the dspOpen routine in
  13191.                                   the ocAccept
  13192.                                   mode, you must specify the value for the
  13193.                                   sendWindow
  13194.                                   parameter that was returned by the dspCLListen
  13195.                                   routine. You
  13196.                                   must provide the value for this parameter when
  13197.                                   you execute the
  13198.                                   dspOpen routine in the ocEstablish mode.
  13199.  
  13200. recvSeq                   The sequence number of the next byte that the local
  13201. connection
  13202.                                  end expects to receive. ADSP uses this number
  13203.                                  to coordinate
  13204.                                  communications and to check for errors. You
  13205.                                  must provide the
  13206.                                  value for this parameter when you execute the
  13207.                                  dspOpen routine
  13208.                                  in the ocEstablish mode. The dspOpen routine
  13209.                                  does not use this
  13210.                                  parameter when you execute it in any other
  13211.                                  mode.
  13212.  
  13213. attnSendSeq          The sequence number of the next attention packet that the
  13214. local
  13215.                                  connection end will transmit. ADSP uses this
  13216.                                  number to
  13217.                                  coordinate communications and to check for
  13218.                                  errors. ADSP
  13219.                                  returns a value for the attnSendSeq parameter
  13220.                                  when you execute
  13221.                                  the dspOpen routine in the ocRequest or
  13222.                                  ocPassive modes. When
  13223.                                  you execute the dspOpen routine in the ocAccept
  13224.                                  mode, you
  13225.                                  must specify the value for the attnSendSeq
  13226.                                  parameter that was
  13227.                                  returned by the dspCLListen routine. You must
  13228.                                  provide the
  13229.                                  value for this parameter when you execute the
  13230.                                  dspOpen routine
  13231.                                  in the ocEstablish mode.
  13232.  
  13233. attnRecvSeq          The sequence number of the next attention packet that the
  13234. local
  13235.                                  connection end expects to receive. ADSP uses
  13236.                                  this number to
  13237.                                  coordinate communications and to check for
  13238.                                  errors. You must
  13239.                                  provide the value for this parameter when you
  13240.                                  execute the
  13241.                                  dspOpen routine in the ocEstablish mode. The
  13242.                                  dspOpen routine
  13243.                                  does not use this parameter when you execute it
  13244.                                  in any other
  13245.                                  mode.
  13246.  
  13247. ocMode                   The mode in which the dspOpen routine is to operate, as
  13248.                                   follows: 
  13249.  
  13250.                                   Mode               Value            Meaning
  13251.                                   ocRequest        1                     ADSP
  13252.                                   attempts to open a connection
  13253.                                                                                
  13254.                                                                                
  13255.                                                                                
  13256.                                                                                
  13257.                                                                                
  13258.  
  13259.   
  13260.                                   ocPassive         2                      The
  13261.                                   connection end waits to receive
  13262.                                                                                
  13263.                                                                                
  13264.                                                                                
  13265.  
  13266.  
  13267.                                   ocAccept          3                       The
  13268.                                   connection server accepts and
  13269.                                                                                
  13270.                                                                                
  13271.                                                                                
  13272.                                                                                
  13273.  
  13274.                                                                                
  13275.                                                                                
  13276.  
  13277.  
  13278.                                    ocEstablish     4                       ADSP
  13279.                                    considers the connection
  13280.                                                                                
  13281.                                                                                
  13282.                                                                                
  13283.                                                                                
  13284.                                                                                
  13285.  
  13286.                                                                                
  13287.                                                                                
  13288.                                                                                
  13289.                                                                                
  13290.                                                                                
  13291.  
  13292.                                                                                
  13293.                                                                                
  13294.                                                                                
  13295.                                                                                
  13296.  
  13297.  
  13298. ocInterval               The period between transmissions of open-connection
  13299. requests.
  13300.                                   If the remote connection end does not
  13301.                                   acknowledge or deny an
  13302.                                   open-connection request, ADSP retransmits the
  13303.                                   request after a
  13304.                                   time period specified by this parameter. The
  13305.                                   time period used by
  13306.                                   ADSP is (ocInterval ¥ 10) ticks; or
  13307.                                   (ocInterval / 6) seconds. For
  13308.                                   example, if you set the ocInterval parameter
  13309.                                   to 3, the time period
  13310.                                   between retransmissions is 30 ticks (1/2
  13311.                                   second). You can set the
  13312.                                   ocInterval parameter to any value from 1 (1/6
  13313.                                   second) to 180 (30
  13314.                                   seconds). If you specify 0 for the ocInterval
  13315.                                   parameter, ADSP uses
  13316.                                   the default value of 6 (1 second).
  13317.  
  13318.                                   You must provide a value for the ocInterval
  13319.                                   parameter when
  13320.                                   you execute the dspOpen routine in the
  13321.                                   ocRequest, ocPassive, or
  13322.                                   ocAccept modes. The dspOpen routine does not
  13323.                                   use this
  13324.                                   parameter when you execute it in the
  13325.                                   ocEstablish mode.
  13326.  
  13327. ocMaximum          The maximum number of times to retransmit an
  13328.                                   open-connection request before ADSP terminates
  13329.                                   execution of
  13330.                                   the dspOpen routine. If you specify 0 for the
  13331.                                   ocMaximum
  13332.                                   parameter, ADSP uses the default value of 3.
  13333.                                   If you specify 255
  13334.                                   for the ocMaximum parameter, ADSP retransmits
  13335.                                   the
  13336.                                   open-connection request indefinitely until the
  13337.                                   remote
  13338.                                   connection end either acknowledges or denies
  13339.                                   the request.
  13340.  
  13341.                                   You must provide a value for the ocMaximum
  13342.                                   parameter when 
  13343.                                   you execute the dspOpen routine in the
  13344.                                   ocRequest, ocPassive, or
  13345.                                   ocAccept modes. The dspOpen routine does not
  13346.                                   use this
  13347.                                   parameter when you execute it in the
  13348.                                   ocEstablish mode.
  13349.  
  13350.    Result codes
  13351.          noErr                                0             No error
  13352.          errOpenDenied      –1273             Open request denied by recepient
  13353.          errOpening             –1277              Attempt to open connection
  13354.          failed
  13355.          errState                    –1278              Connection end must be
  13356.          closed
  13357.          errAborted              –1279              Request aborted by dspRemove
  13358.          or dspClose
  13359.                                                                     routine
  13360.          errRefNum            –1280              Bad connection reference number
  13361.  
  13362. dspNewCID 
  13363.  
  13364.    Parameter block
  13365.             ¨  16            ioResult                 word           result code
  13366.  
  13367.             Æ  24           ioCRefNum           word           driver reference
  13368.             number
  13369.             Æ  26           csCode                     word           always
  13370.             dspNewCID
  13371.             Æ  32           ccbRefNum            word          reference number
  13372.             of CCB
  13373.             ¨  34           newCID                   word          ID of new
  13374.             connection
  13375.  
  13376. The dspNewCID routine causes ADSP to assign an ID to a connection end without
  13377. opening the connection end or attempting to establish a connection with a remote
  13378. connection end. Use this routine only if you implement your own protocol to
  13379. establish communications with a remote connection end. You must first use the
  13380. dspInit routine to establish a connection end. Next, you must call the dspNewCID
  13381. routine to obtain a connection-end ID. Then you must establish communication
  13382. with a remote connection end and pass the ID to the remote connection end.
  13383. Finally, you must call the dspOpen routine in ocEstablish mode to cause ADSP to
  13384. open the connection. See the description of the dspOpen routine for more
  13385. information on establishing a connection in this fashion.
  13386.  
  13387. The ioResult parameter returns the result of the routine. If you call the
  13388. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13389. execution, and it changes the field to the actual result code when it completes
  13390. execution. The ioCRefNum parameter is the driver reference number returned by
  13391. the OpenDriver function. You must specify this number every time you call the
  13392. .DSP driver. The csCode parameter is the routine selector; it is always
  13393. dspNewCID for this routine. The ccbRefNum parameter is the CCB reference number
  13394. that was returned by the dspInit routine. The newCID parameter is the
  13395. connection-end ID returned by this routine. You must provide this number to the
  13396. client of the remote connection end so that it can use it for the remoteCID
  13397. parameter when it calls the dspOpen routine.
  13398.  
  13399.    Result codes
  13400.           noErr                        0        No error
  13401.           errState            –1278        Connection is not closed
  13402.          errRefNum     –1280        Bad connection reference number
  13403.  
  13404. dspClose 
  13405.  
  13406.    Parameter block
  13407.          ¨            16            ioResult              word          result
  13408.          code 
  13409.          Æ            24            ioCRefNum       word         driver
  13410.          reference number
  13411.          Æ            26            csCode                  word         always
  13412.          dspClose
  13413.          Æ           32            ccbRefNum         word         reference
  13414.          number of CCB
  13415.          Æ           34            abort                      byte
  13416.          abort send requests if not 0
  13417.  
  13418. The dspClose routine closes the connection end. The connection end is still
  13419. established; that is, ADSP retains ownership of the CCB, send queue, receive
  13420. queue, and attention-message buffer. You can continue to read bytes from the
  13421. receive queue after you have called the dspClose routine. Use the dspRemove
  13422. routine instead of the dspClose routine if you are through reading bytes from
  13423. the receive queue and want to release the memory associated with the connection
  13424. end. The dspClose routine does not return an error if you call it for a
  13425. connection end that is already closed.
  13426.  
  13427. The ioResult parameter returns the result of the routine. If you call the
  13428. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13429. execution, and it changes the field to the actual result code when it completes
  13430. execution. The ioCRefNum parameter is the driver reference number returned by
  13431. the OpenDriver function. You must specify this number every time you call the
  13432. .DSP driver. The csCode parameter is the routine selector; it is always dspClose
  13433. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13434. returned by the dspInit routine. If the abort parameter is nonzero, ADSP cancels
  13435. any outstanding requests to send data packets (such as the dspAttention routine)
  13436. and discards all data in the send queue. If the abort parameter is 0, ADSP does
  13437. not close the connection end until all of the data in the send queue and all
  13438. outstanding attention messages have been sent and acknowledged.
  13439.  
  13440.    Result codes
  13441.          noErr                          0         No error
  13442.          errRefNum      –1280         Bad connection reference number
  13443.  
  13444. dspRemove 
  13445.  
  13446.    Parameter block
  13447.          ¨          16            ioResult             word        result code 
  13448.          Æ          24            ioCRefNum      word       driver reference
  13449.          number
  13450.          Æ          26            csCode                word       always
  13451.          dspRemove
  13452.          Æ          32            ccbRefNum       word      reference number of
  13453.          CCB
  13454.          Æ          34            abort                    byte        abort
  13455.          connection if not 0
  13456.  
  13457. The dspRemove routine closes any open connection and eliminates the connection
  13458. end; that is, ADSP no longer retains control of the CCB, send queue, receive
  13459. queue, and attention-message buffer. You cannot continue to read bytes from the
  13460. receive queue after you have called the dspRemove routine. After you call the
  13461. dspRemove routine, you can release all of the memory you allocated for the
  13462. connection end if you do not intend to reopen the connection end.
  13463.  
  13464. The ioResult parameter returns the result of the routine. If you call the
  13465. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13466. execution, and it changes the field to the actual result code when it completes
  13467. execution. The ioCRefNum parameter is the driver reference number returned by
  13468. the OpenDriver function. You must specify this number every time you call the
  13469. .DSP driver. The csCode parameter is the routine selector, always dspRemove for
  13470. this routine. The ccbRefNum parameter is the CCB reference number that was
  13471. returned by the dspInit routine. If the abort parameter is nonzero, ADSP cancels
  13472. any outstanding requests to send data packets (such as the dspAttention routine)
  13473. and discards all data in the send queue. If the abort parameter is 0, ADSP does
  13474. not close the connection end until all of the data in the send queue has been
  13475. sent and acknowledged.
  13476.  
  13477.    Result codes
  13478.           noErr                         0         No error
  13479.           errRefNum     –1280         Bad connection reference number
  13480. _______________________________________________________________________________
  13481.  
  13482. æKY Establishing…&…Terminating…an…ADSP…Connection…Listener
  13483. æC »Establishing & Terminating an ADSP Connection Listener               AppleTalk Manager
  13484. _______________________________________________________________________________
  13485.  
  13486. A connection listener is a special kind of connection end that listens for
  13487. open-connection requests from remote connection ends. Connection listeners are
  13488. used by connection servers; that is, programs that assign a socket for the local
  13489. connection end only after they receive a connection request from a remote
  13490. connection end. A single connection listener can receive connection requests
  13491. from any number of remote connection ends. 
  13492.  
  13493. You can use the routines in this section to
  13494.  
  13495.   •  establish a connection listener
  13496.  
  13497.   •  cause the connection listener to wait for a connection request
  13498.  
  13499.   •  deny a connection request
  13500.  
  13501.   •  close and eliminate a connection listener
  13502.  
  13503. dspCLInit 
  13504.  
  13505.    Parameter block
  13506.          ¨       16        ioResult                word       result code 
  13507.          Æ       24        ioCRefNum         word       driver reference number
  13508.          Æ       26        csCode                   word       always dspCLInit
  13509.          ¨       32        ccbRefNum          word       reference number of CCB
  13510.          Æ       34        ccbPtr                      long       pointer to CCB
  13511.          ´       58        localSocket            byte        local DDP socket
  13512.          number
  13513.  
  13514. The dspCLInit routine establishes a connection listener; that is, it assigns a
  13515. specific socket for use by ADSP and initializes the variables that ADSP uses to
  13516. maintain a connection listener. The dspCLInit routine does not cause the
  13517. connection listener to listen for connection requests; you must follow the
  13518. dspCLInit routine with the dspCLListen routine to activate the connection
  13519. listener. Use the dspInit routine to establish a connection end that is not a
  13520. connection listener. Use the dspCLRemove routine to eliminate a connection
  13521. listener.
  13522.  
  13523. The ioResult parameter returns the result of the routine. If you call the
  13524. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13525. execution, and it changes the field to the actual result code when it completes
  13526. execution. The ioCRefNum parameter is the driver reference number returned by
  13527. the OpenDriver function. You must specify this number every time you call the
  13528. .DSP driver. The csCode parameter is the routine selector, always dspCLInit for
  13529. this routine. The dspCLInit routine returns the ccbRefNum parameter, which is
  13530. the CCB reference number. You must provide this number in all subsequent
  13531. dspCLListen and dspCLRemove calls to this connection listener. 
  13532.  
  13533. You must allocate memory for a CCB before you call the dspCLInit routine. The
  13534. ccbPtr parameter is a pointer to the CCB that you allocated. The CCB is 242
  13535. bytes and is described in “The ADSP Connection Control Block” earlier in this
  13536. chapter.
  13537.  
  13538. The localSocket parameter is the DDP socket number of the socket that you want
  13539. ADSP to use for this connection end. Specify 0 for this parameter to cause ADSP
  13540. to assign the socket. In the latter case, ADSP returns the socket number when
  13541. the dspCLInit routine completes execution.
  13542.  
  13543.    Result codes
  13544.          noErr                     0       No error
  13545.          ddpSktErr         –91       Error opening socket
  13546.  
  13547. dspCLListen 
  13548.  
  13549.    Parameter block
  13550.         ¨      16       ioResult               word      result code 
  13551.         Æ      24       ioCRefNum       word      driver reference number
  13552.        Æ       26       csCode                  word     always dspCLListen
  13553.        Æ       32       ccbRefNum         word     reference number of CCB
  13554.        ¨       36       remoteCID           word     ID of remote connection end
  13555.        ¨       38       remoteAddress   long      remote internet address
  13556.        Æ       42       filterAddress       long      filter for open-connection
  13557.        requests
  13558.        ¨       46       sendSeq                long      initial send sequence
  13559.        number
  13560.        ¨       50       sendWindow      word     initial size of remote receive
  13561.        queue
  13562.        ¨       56      attnSendSeq          long      attention send sequence
  13563.        number
  13564.  
  13565. The dspCLListen routine causes a connection listener to listen for connection
  13566. requests. You must have already used the dspCLInit routine to establish a
  13567. connection listener before using the dspCLListen routine. The dspCLListen
  13568. routine is used only by connection servers.
  13569.  
  13570. When ADSP receives an open-connection request from a socket that satisfies the
  13571. address requirements of the filterAddress parameter, it returns values for the
  13572. remoteCID, remoteAddress, sendSeq, sendWindow, and attnSendSeq parameters and
  13573. completes execution of the dspCLListen routine. You must then either accept the
  13574. open-connection request by calling the dspOpen routine in the ocAccept mode or
  13575. deny the request by calling the dspCLDeny routine.
  13576.  
  13577. You can call the dspCLListen routine several times, specifying the same
  13578. connection listener. For example, if you wanted to accept connections from any
  13579. or all of three different addresses, you could call the dspCLListen routine
  13580. three times with a different value for the filterAddress parameter each time.
  13581. Note that you must execute the dspCLListen routine asynchronously to take
  13582. advantage of this feature.
  13583.  
  13584. Fields
  13585.  
  13586. ioResult                        The result of the routine. When you execute the
  13587. routine
  13588.                                         asynchronously, the routine sets this
  13589.                                         parameter to 1 and
  13590.                                         returns a routine result of noErr as
  13591.                                         soon as the routine begins
  13592.                                         execution. When the routine completes
  13593.                                         execution, it sets the
  13594.                                         ioResult parameter to the actual result
  13595.                                         code. 
  13596.  
  13597. ioCRefNum                The driver reference number. This parameter is returned
  13598. by
  13599.                                         the OpenDriver function. You must
  13600.                                         specify this number
  13601.                                         every time you call the .DSP driver. 
  13602.  
  13603. csCode                           The routine selector, always dspCLListen for
  13604. this routine.
  13605.  
  13606. ccbRefNum                 The CCB reference number that was returned by the
  13607. dspCLInit
  13608.                                        routine.
  13609.  
  13610. remoteCID                   The identification number of the remote connection
  13611. end. You
  13612.                                        must pass this value to the dspOpen
  13613.                                        routine when you open
  13614.                                        the connection or to the dspCLDeny
  13615.                                        routine when you deny
  13616.                                        the connection request.
  13617.  
  13618. remoteAddress          The internet address of the remote socket that sent a
  13619. request to
  13620.                                        open a connection. This address consists
  13621.                                        of a 2-byte network
  13622.                                        number, a 1byte node ID, and a 1-byte
  13623.                                        socket number. You
  13624.                                        must pass this value to the dspOpen
  13625.                                        routine when you open
  13626.                                        the connection or to the dspCLDeny
  13627.                                        routine when you deny
  13628.                                        the connection request.
  13629.  
  13630. filterAddress              The internet address of the socket from which you
  13631. will accept
  13632.                                        a connection request. The address
  13633.                                        consists of three fields: a
  13634.                                        2-byte network number, a 1-byte node ID,
  13635.                                        and a 1-byte socket
  13636.                                        number. Specify 0 for any of these fields
  13637.                                        for which you wish to
  13638.                                        impose no restrictions. If you specify a
  13639.                                        filter address of
  13640.                                        $00082500, for example, the connection
  13641.                                        listener accepts a
  13642.                                        connection request from any socket at
  13643.                                        node $25 of network
  13644.                                        $0008. 
  13645.  
  13646. sendSeq                       The sequence number of the first byte that the
  13647. local connection
  13648.                                       end will send to the remote connection
  13649.                                       end. ADSP uses this
  13650.                                       number to coordinate communications and to
  13651.                                       check for 
  13652.                                       errors. You must pass this value to the
  13653.                                       dspOpen routine when
  13654.                                       you open the connection.
  13655.  
  13656. sendWindow            The sequence number of the last byte that the remote
  13657.                                       connection end has buffer space to
  13658.                                       receive. ADSP uses this
  13659.                                       number to coordinate communications and to
  13660.                                       check for
  13661.                                       errors.  You must pass this value to the
  13662.                                       dspOpen routine
  13663.                                       when you open the connection.
  13664.  
  13665. attnSendSeq              The sequence number of the next attention packet that
  13666. the
  13667.                                       local connection end will transmit. ADSP
  13668.                                       uses this number to
  13669.                                       coordinate communications and to check for
  13670.                                       errors. You must
  13671.                                       pass this value to the dspOpen routine
  13672.                                       when you open the
  13673.                                       connection.
  13674.  
  13675.    Result codes
  13676.          noErr                     0         No error
  13677.          errState         –1278         Not a connection listener
  13678.          errAborted   –1279         Request aborted by the dspRemove routine
  13679.          errRefNum  –1280         Bad connection reference number
  13680.  
  13681. dspCLDeny 
  13682.  
  13683.    Parameter block
  13684.        ¨      16       ioResult              word         result code 
  13685.        Æ      24       ioCRefNum       word         driver reference number
  13686.        Æ      26       csCode                  word        always dspCLDeny
  13687.        Æ      32       ccbRefNum         word        reference number of CCB
  13688.        Æ      36       remoteCID           word        ID of remote connection
  13689.        end
  13690.        Æ      38       remoteAddress   long         remote internet address
  13691.  
  13692. The dspCLDeny routine is used by a connection server to inform a remote
  13693. connection end that its request to open a connection cannot be honored.
  13694.  
  13695. The ioResult parameter returns the result of the routine. If you call the
  13696. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13697. execution, and it changes the field to the actual result code when it completes
  13698. execution. The ioCRefNum parameter is the driver reference number returned by
  13699. the OpenDriver function. You must specify this number every time you call the
  13700. .DSP driver. The csCode parameter is the routine selector; it is always
  13701. dspCLDeny for this routine. The ccbRefNum parameter is the CCB reference number
  13702. for the connection listener that received the connection request. This number is
  13703. returned by the dspCLInit routine when you establish a connection listener. The
  13704. remoteCID and remoteAddress parameters specify the address and ID of the remote
  13705. connection end. These parameters are returned by the dspCLListen routine.
  13706.  
  13707.    Result codes
  13708.          noErr                        0       No error
  13709.          errState            –1278       Not a connection listener
  13710.         errAborted       –1279       Request aborted by the dspRemove routine
  13711.         errRefNum     –1280       Bad connection reference number
  13712.  
  13713. dspCLRemove 
  13714.  
  13715.    Parameter block
  13716.         ¨      16       ioResult                word         result code 
  13717.         Æ      24       ioCRefNum         word         driver reference number
  13718.         Æ      26       csCode                   word         always dspCLRemove
  13719.         Æ      32       ccbRefNum          word         reference number of CCB
  13720.         Æ      34       abort                       byte          abort
  13721.         connection listener if not 0
  13722.  
  13723. The dspCLRemove routine closes a connection end used as a connection listener.
  13724. You can release the memory you allocated for the CCB if you do not intend to
  13725. reopen the connection end. 
  13726.  
  13727. The ioResult parameter returns the result of the routine. If you call the
  13728. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13729. execution, and it changes the field to the actual result code when it completes
  13730. execution. The ioCRefNum parameter is the driver reference number returned by
  13731. the OpenDriver function. You must specify this number every time you call the
  13732. .DSP driver. The csCode parameter is the routine selector, always dspCLRemove
  13733. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13734. returned by the dspCLInit routine. If the abort parameter is nonzero, ADSP
  13735. cancels any outstanding requests to send packets (such as the dspCLDeny
  13736. routine). 
  13737.  
  13738.    Result codes
  13739.           noErr                         0           No error
  13740.           errRefNum     –1280           Bad connection reference number
  13741. _______________________________________________________________________________
  13742.  
  13743. æKY Maintaining…an…ADSP…Connection
  13744. æC »Maintaining an ADSP Connection                                       AppleTalk Manager
  13745. _______________________________________________________________________________
  13746.  
  13747. Once you have established a connection end and opened a connection, you must be
  13748. able to send and receive data over the connection. You can use the routines in
  13749. this section to
  13750.  
  13751.   •  determine the status of a connection
  13752.  
  13753.   •  read bytes from the connection end’s receive queue
  13754.  
  13755.   •  write bytes to the connection end’s send queue and transmit them to the
  13756.   remote
  13757.       connection end
  13758.  
  13759.   •  send an attention message to the remote connection end
  13760.  
  13761.   •  discard all data that has been sent but not yet delivered, and reset the
  13762.       connection
  13763.  
  13764. dspStatus 
  13765.  
  13766.    Parameter block
  13767.          ¨       16        ioResult               word       result code 
  13768.          Æ       24        ioCRefNum        word       driver reference number
  13769.          Æ       26        csCode                  word       always dspStatus
  13770.          Æ       32        ccbRefNum         word      reference number of CCB
  13771.          ¨       34        statusCCB            long        pointer to CCB
  13772.          ¨       38        sendQPending    word       bytes waiting to be sent
  13773.          or 
  13774.  
  13775.  
  13776.          ¨       40        sendQFree            word      available send queue
  13777.          in bytes
  13778.          ¨       42        recvQPending     word       bytes waiting to be read
  13779.          from queue
  13780.          ¨       44        recvQFree             word      available receive
  13781.          queue in bytes 
  13782.  
  13783. The dspStatus routine returns the number of bytes waiting to be read and sent
  13784. and the space available in the send and receive queues. This routine also
  13785. returns a pointer to the CCB, which contains information about the state of the
  13786. connection end and about connection events received by the connection end. The
  13787. CCB is described in “The ADSP Connection Control Block” earlier in this chapter.
  13788.  
  13789. The ioResult parameter returns the result of the routine. If you call the
  13790. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13791. execution, and it changes the field to the actual result code when it completes
  13792. execution. The ioCRefNum parameter is the driver reference number returned by
  13793. the OpenDriver function. You must specify this number every time you call the
  13794. .DSP driver. The csCode parameter is the routine selector; it is always
  13795. dspStatus for this routine. The ccbRefNum parameter is the CCB reference number
  13796. that was returned by the dspInit routine. The statusCCB parameter returns a
  13797. pointer to the CCB.
  13798.  
  13799. The sendQPending parameter indicates the number of bytes of data in the send
  13800. queue, including 1 byte for each end-of-message (EOM) indicator in the send
  13801. queue. (ADSP counts 1 byte for each EOM, even though no actual data corresponds
  13802. to the EOM indicator.) The send queue contains all data that has been sent to
  13803. ADSP for transmission and that has not yet been acknowledged. Some of the data
  13804. in the send queue might have already been transmitted, but ADSP retains it in
  13805. the send queue until the remote connection end acknowledges its receipt in case
  13806. the data has to be retransmitted. The sendQFree parameter indicates the number
  13807. of bytes available in the send queue for additional data. 
  13808.  
  13809. The recvQPending parameter indicates the number of bytes in the receive queue,
  13810. including one byte for each EOM if the EOM bit is set in an ADSP packet header.
  13811. The receive queue contains all of the data that has been received by the
  13812. connection end but not yet read by the connection end’s client. The recvQFree
  13813. parameter indicates the number of bytes available in the receive queue for
  13814. additional data.
  13815.  
  13816.    Result codes
  13817.           noErr                            0           No error
  13818.           errRefNum        –1280           Bad connection reference number
  13819.  
  13820. dspRead 
  13821.  
  13822.    Parameter block
  13823.          ¨        16          ioResult               word          result code 
  13824.          Æ        24          ioCRefNum        word          driver reference
  13825.          number
  13826.          Æ        26          csCode                  word          always
  13827.          dspRead
  13828.          Æ        32          ccbRefNum         word         reference number of
  13829.          CCB
  13830.          Æ        34          reqCount              word         requested
  13831.          number of bytes
  13832.          ¨        36          actCount               word         actual number
  13833.          of bytes read
  13834.          Æ        38          dataPtr                   long          pointer to
  13835.          data buffer
  13836.          ¨        42          eom                        byte           1 if
  13837.          end-of-message; 0 otherwise
  13838.  
  13839. The dspRead routine reads bytes from the connection end’s receive queue and
  13840. places them in a buffer that you specify. You can continue to read bytes as long
  13841. as data is in the receive queue, even after you have called the dspClose routine
  13842. or after the remote connection end has called the dspClose or dspRemove
  13843. routines. The dspRead routine completes execution when it has read the number of
  13844. bytes you specify or when it encounters an end-of-message (that is, the last
  13845. byte of data in an ADSP packet that has the EOM bit set in the packet header).
  13846.  
  13847. You can call the dspStatus routine to determine the number of bytes remaining to
  13848. be read from the read queue, or you can continue to call the dspRead routine
  13849. until the actCount and eom parameters both return 0.
  13850.  
  13851. The ioResult parameter returns the result of the routine. If you call the
  13852. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13853. execution, and it changes the field to the actual result code when it completes
  13854. execution. The ioCRefNum parameter is the driver reference number returned by
  13855. the OpenDriver function. You must specify this number every time you call the
  13856. .DSP driver. The csCode parameter is the routine selector; it is always dspRead
  13857. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13858. returned by the dspInit routine. 
  13859.  
  13860. You specify the number of bytes to read with the reqCount parameter, and you use
  13861. the dataPtr parameter to provide a pointer to the buffer into which ADSP should
  13862. place the data. ADSP returns the actual number of bytes read in the actCount
  13863. parameter. If the last byte read constitutes an EOM, ADSP sets the eom parameter
  13864.  
  13865. to 1.
  13866.  
  13867. If either end closes the connection before you call the dspRead routine, the
  13868. command reads whatever data is available and returns the actual amount of data
  13869. read in the actCount parameter. If the connection is closed and there is no data
  13870. in the receive queue, the dspRead routine returns the noErr result code with the
  13871. actCount parameter set to 0 and the eom parameter set to 0.
  13872.  
  13873.    Result codes
  13874.           noErr                          0          No error
  13875.           errFwdReset     –1275          Read terminated by forward reset
  13876.           errState              –1278          State isn’t open, closing, or
  13877.           closed
  13878.           errAborted        –1279          Request aborted by dspRemove or
  13879.           dspClose routine
  13880.           errRefNum      –1280          Bad connection reference number
  13881.  
  13882. dspWrite 
  13883.  
  13884.    Parameter block
  13885.         ¨      16       ioResult              word           result code 
  13886.         Æ      24       ioCRefNum       word          driver reference number
  13887.         Æ      26       csCode                 word          always dspWrite
  13888.         Æ      32       ccbRefNum        word          reference number of CCB
  13889.         Æ      34       reqCount             word          requested number of
  13890.         bytes
  13891.         ¨      36       actCount              word          actual number of
  13892.         bytes written
  13893.         Æ      38       dataPtr                  long           pointer to data
  13894.         buffer
  13895.         Æ      42       eom                       byte            1 if end of
  13896.         message; 0 otherwise
  13897.         Æ      43       flush                      byte            1 to send
  13898.         data now; 0 otherwise
  13899.  
  13900. The dspWrite routine writes bytes into the connection end’s send queue. The send
  13901. queue contains all data that has been sent to ADSP for transmission and that has
  13902. not yet been acknowledged. Some of the data in the send queue might have already
  13903. been transmitted, but ADSP retains it in the send queue until the remote
  13904. connection end acknowledges its receipt in case the data has to be
  13905. retransmitted. The dspWrite routine completes execution when it has copied all
  13906. of the data from the data buffer into the ADSP send queue.
  13907.  
  13908. ADSP transmits the data in the send queue when the remote connection end has
  13909. room to accept the data and one of the following conditions occurs:
  13910.  
  13911.   •  You call the dspWrite routine with the flush parameter set to a nonzero
  13912.        number.
  13913.  
  13914.   •  The number of bytes in the send queue equals or exceeds the blocking
  13915.   factor.
  13916.        (You use the sendBlocking parameter to the dspOptions routine to set the
  13917.        blocking factor.)
  13918.  
  13919.   •  The send timer expires.
  13920.  
  13921.   •  A connection event requires that the local connection end send an
  13922.        acknowledgment packet to the remote connection end.
  13923.  
  13924. The ioResult parameter returns the result of the routine. If you call the
  13925. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13926. execution, and it changes the field to the actual result code when it completes
  13927. execution. The ioCRefNum parameter is the driver reference number returned by
  13928. the OpenDriver function. You must specify this number every time you call the
  13929. .DSP driver. The csCode parameter is the routine selector; it is always dspWrite
  13930. for this routine. The ccbRefNum parameter is the CCB reference number that was
  13931. returned by the dspInit routine. 
  13932.  
  13933. You specify the number of bytes to write with the reqCount parameter, and you
  13934. use the dataPtr parameter to provide a pointer to the buffer from which ADSP
  13935. should read the data. The dspWrite routine returns the actual number of bytes
  13936. written in the actCount parameter. If the last byte written constitutes an EOM,
  13937. set the eom parameter to 1. You can also set the reqCount parameter to 0 and the
  13938. eom parameter to 1 to indicate that the last byte you sent the previous time you
  13939. called the dspWrite routine was the end of the message. The high-order bits of
  13940. the eom parameter are reserved for use by ADSP; you must leave these bits equal
  13941. to 0.
  13942.  
  13943. You can set the reqCount parameter to a value larger than the size of the send
  13944. queue. If you do so, the dspWrite routine writes as much data as it can into the
  13945. send queue, sends the data and waits for acknowledgment, and then writes more
  13946. data into the send queue until it has written the amount of data you requested.
  13947. In this case, the routine does not complete execution until it has finished
  13948. writing all of the data into the send queue. 
  13949.  
  13950. Set the flush parameter to 1 to cause ADSP to immediately transmit any data in
  13951. the send queue that has not already been transmitted. Set the flush parameter to
  13952. 0 to allow data to accumulate in the send queue until another condition occurs
  13953. that causes data to be transmitted. The high-order bits of the flush parameter
  13954. are reserved for use by ADSP; you must leave these bits equal to 0.
  13955.  
  13956.    Result codes
  13957.           noErr                        0         No error
  13958.           errState            –1278         Connection is not open
  13959.           errAborted      –1279         Request aborted by dspRemove or dspClose
  13960.           routine
  13961.           errRefNum    –1280         Bad connection reference number
  13962.  
  13963. dspAttention 
  13964.  
  13965.    Parameter block
  13966.         ¨       16        ioResult            word         result code 
  13967.         Æ       24        ioCRefNum     word         driver reference number
  13968.         Æ       26        csCode               word         always dspAttention
  13969.         Æ       32        ccbRefNum      word         reference number of CCB
  13970.         Æ       34        attnCode           word         client attention code
  13971.         Æ       36        attnSize             word         size of attention
  13972.         data in bytes
  13973.         Æ       38        attnData             long          pointer to
  13974.         attention data
  13975.  
  13976. The dspAttention routine sends an attention code and an attention message to the
  13977. remote connection end. Attention codes and attention messages can have any
  13978. meaning that your application and the application at the remote connection end
  13979. both recognize. The purpose of attention codes and messages is to allow clients
  13980. of ADSP to send messages outside the normal data stream. For example, if a
  13981. connection end on a mainframe computer is connected to several connection ends
  13982. in Macintosh computers being used as remote terminals, the mainframe computer
  13983. might wish to inform the remote terminals that all connections will be
  13984. terminated in ten minutes. The mainframe application could send an attention
  13985. message to each of the remote terminals informing them of this fact, and the
  13986. terminal emulation programs in the Macintosh computers could then display an
  13987. alert message on the screen so that the users could prepare to shut down.
  13988.  
  13989. The ioResult parameter returns the result of the routine. If you call the
  13990. routine asynchronously, the routine sets this field to 1 as soon as it begins
  13991. execution, and it changes the field to the actual result code when it completes
  13992. execution. The ioCRefNum parameter is the driver reference number returned by
  13993. the OpenDriver function. You must specify this number every time you call the
  13994. .DSP driver. The csCode parameter is the routine selector; it is always
  13995. dspAttention for this routine. The ccbRefNum parameter is the CCB reference
  13996. number that was returned by the dspInit routine. 
  13997.  
  13998. The attnCode parameter is the attention code that you wish to send to the remote
  13999. connection end. You can use any value from $0000 through $EFFF for the attention
  14000. code. The values $F000 through $FFFF are reserved for use by ADSP. The attnSize
  14001. parameter is the size in bytes of the attention message you wish to send, and
  14002. the attnData parameter provides a pointer to the attention message. The
  14003. attention message can be any size from 0 through 570 bytes. There are no
  14004. restrictions on the content of the attention message.
  14005.  
  14006.    Result codes
  14007.           noErr                         0       No error
  14008.           errAttention    –1276       Attention message too long
  14009.           errState             –1278        Connection is not open
  14010.           errAborted       –1279        Request aborted by dspRemove or dspClose
  14011.           routine
  14012.           errRefNum     –1280        Bad connection reference number
  14013.  
  14014. dspReset 
  14015.  
  14016.    Parameter block
  14017.          ¨        16      ioResult           word       result code 
  14018.          Æ        24      ioCRefNum    word      driver reference number
  14019.          Æ        26      csCode              word      always dspReset
  14020.          Æ        32      ccbRefNum     word      reference number of CCB
  14021.  
  14022. The dspReset routine causes ADSP to discard all data in the send queue, all data
  14023. in transit to the remote connection end, and all data in the remote connection
  14024. end’s receive queue that the client has not yet read. This process is known as a
  14025. forward reset. ADSP then resynchronizes the connection. You can determine that
  14026. your connection end has received a forward reset and has discarded all data in
  14027. the receive queue by checking the eFwdReset flag in the userFlags field of the
  14028. CCB. The CCB is described in “The ADSP Connection Control Block” earlier in this
  14029. chapter. 
  14030.  
  14031. The ioResult parameter returns the result of the routine. If you call the
  14032. routine asynchronously, the routine sets this field to 1 as soon as it begins
  14033. execution, and it changes the field to the actual result code when it completes
  14034. execution. The ioCRefNum parameter is the driver reference number returned by
  14035. the OpenDriver function. You must specify this number every time you call the
  14036. .DSP driver. The csCode parameter is the routine selector; it is always dspReset
  14037. for this routine. The ccbRefNum parameter is the CCB reference number that was
  14038. returned by the dspInit routine. 
  14039.  
  14040.    Result codes
  14041.           noErr                         0       No error
  14042.           errState             –1278       Connection is not open
  14043.           errAborted       –1279       Request aborted by dspRemove or dspClose
  14044.           routine
  14045.           errRefNum     –1280       Bad connection reference number
  14046. _______________________________________________________________________________
  14047.  
  14048. æKY The….ENET…Driver…Volume…VI
  14049. æC »The .ENET Driver Volume VI                                           AppleTalk Manager
  14050. _______________________________________________________________________________
  14051.  
  14052. The .ENET driver is normally called by the AppleTalk Manager through the
  14053. AppleTalk connection file for EtherTalk when the user has selected EtherTalk
  14054. from the Network control panel. You can write your own protocol stack or
  14055. application that uses the .ENET driver directly, rather than through AppleTalk.
  14056. This section describes how to open the .ENET driver, how to send data to it
  14057. directly for transmission over the Ethernet network, and how to write a protocol
  14058. handler to receive data from the network. 
  14059.  
  14060. The system .ENET driver locates and opens the drivers for installed NuBus®
  14061. Ethernet cards. For each Ethernet NuBus card, the .ENET driver searches the open
  14062. resource files for a driver with a resource type of 'enet' and a resource ID
  14063. equal to the board ID of the NuBus card. If it doesn't find such a driver
  14064. resource, it then looks for a driver named .ENET in the slot resources in the
  14065. ROM of the NuBus card. See Designing Cards and Drivers for the Macntosh Family
  14066. for discussions of NuBus board IDs and slot resources.
  14067.  
  14068. _______________________________________________________________________________
  14069.  
  14070. æKY Providing…Your…Own…Ethernet…Driver
  14071. æC »Providing Your Own Ethernet Driver                                   AppleTalk Manager
  14072. _______________________________________________________________________________
  14073.  
  14074. If you write an Ethernet driver for use with your own Ethernet NuBus card, you
  14075. should provide the features and functions described in this chapter. You can
  14076. store the driver in the firmware of the NuBus card as described in Designing
  14077. Cards and Drivers for the Macntosh Family  and in the Device Manager chapter of
  14078. Inside Macintosh , Volume V, or you can provide a RAM-based driver as described
  14079. in the Device Manager chapter of Inside Macintosh , Volume II. If you place your
  14080. Ethernet driver in the ROM of the NuBus card, you must name the driver .ENET. If
  14081. you provide a RAM-based driver, you must give it a resource type of 'enet' and a
  14082. resource ID equal to the board ID of your NuBus card. The 'enet' resource type
  14083. is identical to the 'DRVR' resource type described in the Device Manager chapter
  14084. of Volume II. 
  14085.  
  14086.    Note:  You must not name a RAM-based driver “.ENET,” because doing so would
  14087.    replace the system .ENET driver. 
  14088.  
  14089. If you write an Ethernet driver for use with a non-NuBus network interface (such
  14090. as an Ethernet card for the Macintosh SE/30 or an Ethernet connection through
  14091. the SCSI port), you should provide the features and functions described in this
  14092. chapter for the .ENET driver and should name your driver .ENET0. If you do so,
  14093. any software written to use the .ENET driver should work with your driver.
  14094.  
  14095. _______________________________________________________________________________
  14096.  
  14097. æKY Changing…the…Ethernet…Hardware…Address
  14098. æC »Changing the Ethernet Hardware Address                               AppleTalk Manager
  14099. _______________________________________________________________________________
  14100.  
  14101. Each Ethernet NuBus card or other Ethernet hardware interface device contains a
  14102. unique 6-byte hardware address assigned by the manufacturer of the device. The
  14103. .ENET driver normally uses this address to determine whether to receive a
  14104. packet. To change the hardware address for your node, place in the System file a
  14105. resource of type 'eadr' with a resource ID equal to the slot number of the
  14106. Ethernet NuBus card. If the Ethernet device is not a NuBus card (it might be a
  14107. slot card in a Macintosh SE/30, for example), use a resource ID of 0. 
  14108.  
  14109. The 'eadr' resource consists only of a 6-byte number. Do not use the broadcast
  14110. address or a multicast address for this number. (The broadcast address is
  14111. $FF-FF-FF-FF-FF-FF. A multicast address is any Ethernet address in which the
  14112. low-order bit of the high-order byte is set to 1.) When you open the .ENET
  14113. driver, it looks for an 'eadr' resource. If it finds one, the driver substitutes
  14114. the number in this resource for the Ethernet hardware address and uses it until
  14115. the driver is closed or reset. 
  14116.  
  14117.    Note:  To avoid address collisions, you should never arbitrarily change the
  14118.    Ethernet hardware address. This feature should be used only by a system
  14119.    administrator who can keep track of all the Ethernet addresses in the system.
  14120.  
  14121. _______________________________________________________________________________
  14122.  
  14123. æKY Opening…the….ENET…Driver
  14124. æC »Opening the .ENET Driver                                             AppleTalk Manager
  14125. _______________________________________________________________________________
  14126.  
  14127. Before you use the OpenSlot function to open the .ENET driver, you must
  14128. determine which NuBus slots contain EtherTalk cards. The OpenSlot function is
  14129. described in the Device Manager chapter of Volume V. Use the SGetTypesRsrc
  14130. function described in the Slot Manager chapter of this volume to determine which
  14131. NuBus slots contain EtherTalk cards. To find EtherTalk NuBus cards, use the
  14132. value catNetwork in the field spCategory of the GetTypesRsrc function parameter
  14133. block, and use the value typEtherNet in the field spCType. If you cannot find
  14134. any EtherTalk NuBus cards, you should also attempt to open the .ENET0 driver in
  14135. case a non-NuBus EtherTalk card is attached to the system. You should provide a
  14136. user interface that allows the user to select a specific EtherTalk card in the
  14137. case that more than one is present.
  14138.  
  14139. Listing 32-7 illustrates the use of the GetTypesRsrc function and the OpenSlot
  14140. function to open the .ENET driver.
  14141.  
  14142. ¿ Listing 32-7   Finding an EtherTalk card and opening the .ENET driver
  14143.  
  14144. VAR
  14145.    mySBlk:      SpBlock;
  14146.    myPBRec:     ParamBlockRec;
  14147.    myErr:       OSErr;
  14148.    Found:       Integer;
  14149.    EnetStr:     Str15;
  14150.    Enet0Str:    Str15;
  14151.    myRefNum:    Integer;
  14152.  
  14153. BEGIN
  14154.    Found := 0;              {assume no sResource found}
  14155.    EnetStr := '.ENET';
  14156.    Enet0Str := '.ENET0';
  14157.  
  14158.    REPEAT
  14159.       WITH mySBlk DO
  14160.       BEGIN
  14161.           spParamData := 1;  {include search of disabled resources. }
  14162.                              { Start searching from spSlot and search }
  14163.                              { the slots above it as well.}
  14164.           spCategory := catNetwork;
  14165.           spCType := typeEtherNet;
  14166.           spDrvrSW := 0;
  14167.           spDrvrHW := 0;
  14168.           spTBMask := 3;     {match only Category and CType fields}
  14169.           spSlot := 0;       {start search from here}
  14170.           spID := 0;         {start search from here}
  14171.           spExtDev :=  0;    {ID of the external device}
  14172.       END;
  14173.       myErr := SGetTypeSRsrc(@mySBlk);
  14174.       IF myErr = noErr THEN
  14175.       {We found an sResource match, save it for later. }
  14176.       BEGIN
  14177.          Found := Found + 1;
  14178.          SaveSInfo(@mySBlk);
  14179.       END;
  14180.    UNTIL myErr = smNoMoresRsrcs;
  14181.  
  14182.    IF Found > 1 THEN
  14183.    BEGIN
  14184.       {If you found more than one sResource, put up a dialog box }
  14185.       { and let the user choose one. If any of the sResources you }
  14186.       { found were disabled, let the user know they are not available. }
  14187.       DisplaySInfo(@mySBLk);
  14188.    END;
  14189.  
  14190.    IF Found <> 0 THEN
  14191.    BEGIN  
  14192.       WITH myPBRec DO
  14193.       BEGIN
  14194.          ioCompletion := NIL;
  14195.          ioNamePtr := @EnetStr;
  14196.          ioMix := NIL;      {reserved}
  14197.          ioFlags := 0;      {single device sResource}
  14198.          ioSlot := mySBlk.spSlot;
  14199.          ioID := mySBlk.spID;
  14200.       END;
  14201.       myErr := OpenSlot(@myPBRec, FALSE);    {go open this}
  14202.    END
  14203.    ELSE myErr := OpenDriver(Enet0Str, myRefNum);
  14204.    IF myErr <> NoErr THEN DoError(myErr);
  14205. END;
  14206. _______________________________________________________________________________
  14207.  
  14208. æKY Using…a…Write-Data…Structure…to…Transmit…Ethernet…Data
  14209. æC »Using a Write-Data Structure to Transmit Ethernet Data               AppleTalk Manager
  14210. _______________________________________________________________________________
  14211.  
  14212. When you use the EWrite function to send data to the .ENET driver for
  14213. transmission over the Ethernet network, you provide a pointer to a write-data
  14214. structure (Figure 32-5). A write-data structure contains a series of pairs of
  14215. length words and pointers. Each pair indicates the length and location of a
  14216. portion of the data that constitutes the packet to be sent over the network. The
  14217. first length-pointer pair points to a 14-byte header block, which starts with
  14218. the destination node hardware address. Note that this is not the AppleTalk
  14219. address, but is the hardware address of the destination node. If you are calling
  14220. the .ENET driver directly, you must obtain the Ethernet address of the
  14221. destination node yourself; AppleTalk cannot provide it. 
  14222.  
  14223. The next 6 bytes of the header block are reserved for use by the .ENET driver.
  14224. These bytes are followed by the 2-byte Ethernet protocol type. Data may follow
  14225. the header block; all other length-pointer pairs point to data. The write-data
  14226. structure terminates with a 0 word.
  14227.  
  14228. ¿ Figure 32-5   An Ethernet write-data structure ø 
  14229.  
  14230. When you first open the .ENET driver, it allocates a 768-byte buffer that it
  14231. uses for transmitting data packets. This buffer is large enough to hold the
  14232. largest EtherTalk packet, which is 621 bytes in size. If you want to transmit
  14233. data packets larger than 768 bytes, call the ESetGeneral function. The .ENET
  14234. driver then allocates a large enough data buffer to send packets up to 1514
  14235. bytes in size.
  14236.  
  14237. Listing 32-8 defines an Ethernet write-data structure and then calls the EWrite
  14238. function to send a data packet over Ethernet.
  14239.  
  14240. ¿ Listing 32-8   Sending a data packet over Ethernet
  14241.  
  14242. CONST
  14243.    size1  =  100;
  14244.    size2  =  333;
  14245.   
  14246. TYPE
  14247.    WDS  =  RECORD                  {write-data structure}
  14248.            length : Integer;       {length of nth entry}
  14249.            aptr : Ptr;             {pointer to nth entry}
  14250.         END;
  14251.  
  14252. VAR
  14253.    myWDS:  ARRAY [1..4] OF WDS;
  14254.    myPB:    EParamBlock;           {.ENET parameter block}
  14255.    wheader:  ARRAY [1..14] OF Byte;
  14256.    stuff1:  ARRAY [1..size1] OF Byte;
  14257.    stuff2:  ARRAY [1..size2] OF Byte;
  14258.    myErr:  OSErr;  
  14259.   
  14260. BEGIN
  14261.    {set up the write header}
  14262.    wheader[1] := $02;              {dest node ID}
  14263.    wheader[2] := $60;
  14264.    wheader[3] := $8C;
  14265.    wheader[4] := $04;
  14266.    wheader[5] := $05;
  14267.    wheader[6] := $06;
  14268.                                    {bytes 7-12 are reserved}
  14269.    wheader[13] := $08;             {protocol type}
  14270.    wheader[14] := $00;
  14271.   
  14272.    myWDS[1].length := 14;          {the write header is always 14 bytes}
  14273.    myWDS[1].aptr := @wheader;
  14274.    myWDS[2].length := size1;
  14275.    myWDS[2].aptr := @stuff1;
  14276.    myWDS[3].length := size2;
  14277.    myWDS[3].aptr := @stuff2;
  14278.    myWDS[4].length := 0;           {terminator}
  14279.  
  14280.    myPB.ePointer := @myWDS;        {pointer to write data structure}
  14281.    myErr := EWrite(@myPB, FALSE);  {send something}
  14282.    IF myErr <> NoErr THEN DoError(myErr);
  14283. END;
  14284. _______________________________________________________________________________
  14285.  
  14286. æKY Using…the…Default…Ethernet…Protocol…Handler…to…Read…Data
  14287. æC »Using the Default Ethernet Protocol Handler to Read Data             AppleTalk Manager
  14288. _______________________________________________________________________________
  14289.  
  14290. When the EtherTalk Nubus card or other Ethernet hardware receives a data packet,
  14291. it generates an interrupt to the CPU. The interrupt handler in ROM determines
  14292. the source of the interrupt and calls the .ENET driver. The .ENET driver reads
  14293. the packet header to determine the protocol type of the data packet and checks
  14294. to see if any client has specified that protocol type in a call to the EAttachPH
  14295. function. If so, the client either specified a NIL pointer to a protocol
  14296. handler, or the client provided its own protocol handler. If the client
  14297. specified a NIL pointer, the .ENET driver uses its default protocol handler to
  14298. read the data. If no one has specified that protocol type in a call to the
  14299. EAttachPH function, the .ENET driver discards the data. The EAttachPH function
  14300. is described in “Attaching and Detaching an Ethernet Protocol Handler” later in
  14301. this chapter.
  14302.  
  14303. The default protocol handler checks for an ERead function pending execution and
  14304. places the entire packet—including the packet header—into the buffer specified
  14305. by that function. The function returns the number of bytes actually read. If the
  14306. packet is larger than the data buffer, the ERead function places as much of the
  14307. packet as will fit into the buffer and returns the buf2SmallErr result code.
  14308.  
  14309. Call the ERead function asynchronously to await the next data packet. When the
  14310. .ENET driver receives the data packet, it completes execution of the ERead
  14311. function and calls your completion routine. Your completion routine should call
  14312. the ERead function again so that an ERead function is always pending execution.
  14313. If the .ENET driver receives a data packet with a protocol type for which you
  14314. specified the default protocol handler while no ERead function is pending, the
  14315. .ENET driver discards the packet.
  14316.  
  14317. You can have several asynchronous calls to the ERead function pending execution
  14318. simultaneously as long as you use different buffers and a different parameter
  14319. block for each call.
  14320.  
  14321. Listing 32-9 calls the EAttachPH function to specify that the .ENET driver
  14322. should use the default protocol handler to process protocol type MyPType. The
  14323. listing includes a completion routine that processes a received data packet and
  14324. then makes an asynchronous call to the ERead function to await the next incoming
  14325. data packet. 
  14326. In practice, you should call the EAttachPH function very early, during your
  14327. program initialization sequence, if possible. As soon as the connection is
  14328. established and you are expecting data, you should call the ERead function
  14329. asynchronously. When the .ENET driver receives a packet, it then calls your
  14330. completion routine, which should process the packet and queue another
  14331. asynchronous call to the ERead function to await the next packet. 
  14332.  
  14333. ¿ Listing 32-9   Using the default Ethernet protocol handler to read data
  14334.  
  14335. CONST
  14336.    BigBytes = 8888;
  14337.  
  14338. VAR
  14339.    myPB:     EParamBlock;
  14340.    EPBPtr:   EParamBlkPtr;
  14341.    APtr:     Ptr;
  14342.    myErr:    OSErr;  
  14343.  
  14344.    PROCEDURE MyCompRoutine;
  14345.  
  14346.    VAR
  14347.       myErr:  OSErr;  
  14348.   
  14349.    BEGIN
  14350.    {If this gets called, an incoming packet with the specified protocol }
  14351.    { type is here.}
  14352.   
  14353.       ProcessData(BigBytes, APtr);           {do something with the data}
  14354.       IF EPBPtr^.ioResult <> noErr THEN DoError(myErr);
  14355.   
  14356.       {call ERead again}
  14357.       WITH EPBPtr^ DO                        {set up ERead parameters}
  14358.       BEGIN
  14359.          ioCompletion := @MyCompRoutine;     {pointer to completion routine}
  14360.          eProtType := 77;                    {protocol type}
  14361.          ePointer := APtr;                   {pointer to read data area}
  14362.          eBuffSize := BigBytes;              {size of read data area}
  14363.       END;
  14364.       myErr := ERead(EPBPtr, TRUE);          {call ERead to wait for }
  14365.                                              { the next packet}
  14366.       IF myErr <> noErr THEN DoError(myErr);  
  14367.    END;
  14368.  
  14369. BEGIN  {main}
  14370.    EPBPtr := @myPB;
  14371.    WITH EPBPtr^ DO                        {set up EAttachPH parameters}
  14372.    BEGIN
  14373.       eProtType := 77;                    {protocol type}
  14374.       ePointer := NIL;                    {use default protocol handler}
  14375.    END;  
  14376.    myErr := EAttachPH(EPBPtr, FALSE);     {tell .ENET about this }
  14377.                                           { protocol handler}
  14378.    IF myErr <> NoErr THEN DoError(myErr);
  14379.   
  14380.    APtr := NewPtr(BigBytes);
  14381.    WITH EPBPtr^ DO                        {set up ERead parameters}
  14382.    BEGIN
  14383.       ioCompletion := @MyCompRoutine;     {pointer to completion routine}
  14384.       eProtType := 77;                    {protocol type}
  14385.       ePointer := APtr;                   {pointer to read data area}
  14386.       eBuffSize := BigBytes;              {size of read data area}
  14387.    END;
  14388.    myErr := ERead(EPBPtr, TRUE);          {wait for your packet and }
  14389.                                           { then read it}
  14390.    IF myErr <> noErr THEN DoError(myErr);
  14391.   
  14392.    {application-defined tasks}
  14393.   
  14394. END;  {main}
  14395.  
  14396. _______________________________________________________________________________
  14397.  
  14398. æKY Using…Your…Own…Ethernet…Protocol…Handler…to…Read…Data
  14399. æC »Using Your Own Ethernet Protocol Handler to Read Data                AppleTalk Manager
  14400. _______________________________________________________________________________
  14401.  
  14402. If a client of the .ENET driver has used the EAttachPH function to provide a
  14403. pointer to its own protocol handler, the .ENET driver calls that protocol
  14404. handler, which must in turn call the .ENET driver’s ReadPacket and ReadRest
  14405. routines to read the data. Your protocol handler calls the .ENET driver’s
  14406. ReadPacket and ReadRest routines in essentially the same way as you call the
  14407. .MPP drivers ReadPacket and ReadRest routines (see the AppleTalk Manager chapter
  14408. of Volume II). The following sections describe how the .ENET driver calls a
  14409. custom protocol handler and the ReadPacket and ReadRest routines.
  14410.  
  14411.    Note:  Because an Ethernet protocol handler must read from and write to the
  14412.    CPU’s registers, you cannot write a protocol handler in Pascal. 
  14413.  
  14414. _______________________________________________________________________________
  14415.  
  14416. æKY How…the….ENET…Driver…Calls…Your…Protocol…Handler
  14417. æC »How the .ENET Driver Calls Your Protocol Handler                     AppleTalk Manager
  14418. _______________________________________________________________________________
  14419.  
  14420. You can provide an Ethernet protocol handler for a particular protocol type and
  14421. use the EAttachPH function to attach it to the .ENET driver. When the driver
  14422. receives an Ethernet packet, it reads the packet header into an internal buffer,
  14423. reads the protocol type, and calls the protocol handler for that protocol type.
  14424. The CPU is in interrupt mode, and the registers are used as follows:
  14425.  
  14426. Registers on call to Ethernet protocol handler
  14427.  
  14428. A0                            Reserved for internal use by the .ENET driver. You
  14429. must 
  14430.                                  preserve this register until after the ReadRest
  14431.                                  routine has
  14432.                                  completed execution.
  14433.  
  14434. A1                           Reserved for internal use by the .ENET driver. You
  14435. must
  14436.                                 preserve this register until after the ReadRest
  14437.                                 routine has
  14438.                                 completed execution.
  14439.  
  14440. A2                           Free for your use.
  14441.  
  14442. A3                           Pointer to first byte past data-link header bytes
  14443. (the first byte after
  14444.                                 the 2-byte protocol-type field).
  14445.  
  14446. A4                           Pointer to the ReadPacket routine. The ReadRest
  14447. routine starts 2
  14448.                                  bytes after the start of the ReadPacket
  14449.                                  routine.
  14450.  
  14451. A5                           Free for your use until after the ReadRest routine
  14452. has completed
  14453.                                  execution.
  14454.  
  14455. D0                           Free for your use.
  14456.  
  14457. D1                           Number of bytes in the Ethernet packet left to be
  14458. read (that is, the
  14459.                                  number of bytes following the Ethernet header).
  14460.  
  14461. D2                           Free for your use.
  14462.  
  14463. D3                           Free for your use.
  14464.  
  14465. If your protocol handler processes more than one protocol type, you can read the
  14466. protocol-type field in the data-link header to determine the protocol type of
  14467. the packet. The protocol-type field starts 2 bytes before the address pointed to
  14468. by the A3 register. 
  14469.  
  14470.    Note:  The source address starts 8 bytes before the address pointed to by the
  14471.    A3
  14472.    register, and the destination address starts 14 bytes before the address
  14473.    pointed to
  14474.    by the A3 register.
  14475.  
  14476. If you know that the packet contains pad bytes and you know the actual size of
  14477. the data, you can reduce the number in the D1 register by the number of pad
  14478. bytes so that the .ENET driver can keep accurate track of the number of bytes
  14479. remaining to be read. In all other circumstances, you should not change the
  14480. value in the D1 register. 
  14481.  
  14482. After you have called the ReadRest routine, you can use registers A0 through A3
  14483. and D0 through D3 for your own use, but you must preserve all other registers.
  14484. You cannot depend on having access to your application global variables.
  14485.  
  14486. _______________________________________________________________________________
  14487.  
  14488. æKY How…Your…Protocol…Handler…Calls…the….ENET…Driver
  14489. æC »How Your Protocol Handler Calls the .ENET Driver                     AppleTalk Manager
  14490. _______________________________________________________________________________
  14491.  
  14492. Your protocol handler must call the .ENET driver routines ReadPacket and
  14493. ReadRest to read the incoming data packet. You may call the ReadPacket routine
  14494. as many times as you like to read the data piece by piece into one or more data
  14495. buffers, but you must always use the ReadRest routine to read the final piece of
  14496. the data packet. The ReadRest routine restores the machine state (the stack
  14497. pointers, status register, and so forth) and checks for error conditions. 
  14498.  
  14499. Before you call the ReadPacket routine, you must allocate memory for a data
  14500. buffer and place a pointer to the buffer in the A3 register. You place the
  14501. number of bytes you want to read in the D3 register. You must not request more
  14502. bytes than remain in the data packet. 
  14503.  
  14504. To call the ReadPacket routine, execute a JSR instruction to the address in the
  14505. A4 register. The ReadPacket routine uses the registers as follows:
  14506.  
  14507. Registers on entry to the ReadPacket routine
  14508.  
  14509. A3                             Pointer to a buffer to hold the data you want to
  14510. read
  14511.  
  14512. D3                             Number of bytes to read; must be nonzero
  14513.  
  14514. Registers on exit from the ReadPacket routine
  14515.  
  14516. A0                             Unchanged
  14517.  
  14518. A1                             Unchanged
  14519.  
  14520. A2                             Unchanged
  14521.  
  14522. A3                             First byte after the last byte read into buffer
  14523.  
  14524. D0                             Changed
  14525.  
  14526. D1                             Number of bytes left to be read
  14527.  
  14528. D2                             Unchanged
  14529.  
  14530. D3                             Equals 0 if requested number of bytes were read,
  14531. nonzero if error
  14532.  
  14533. The ReadPacket routine indicates an error by clearing to 0 the zero (z) flag in
  14534. the status register. If the ReadPacket routine returns an error, you must
  14535. terminate execution of your protocol handler with an RTS instruction without
  14536. calling ReadPacket again or calling ReadRest at all.
  14537.  
  14538. Call the ReadRest routine to read the last portion of the data packet, or call
  14539. it after you have read all the data with ReadPacket routines and before you do
  14540. any other processing or terminate execution. You must provide in the A3 register
  14541. a pointer to a data buffer and must indicate in the D3 register the size of the
  14542. data buffer. If you have already read all of the data with calls to the
  14543. ReadPacket routine, you can specify a buffer of size 0.
  14544.  
  14545.     †   Warning:  If you do not call the ReadRest routine after your last call
  14546.     to the
  14547.         ReadPacket routine, the system will crash.  Ê
  14548.  
  14549. To call the ReadRest routine, execu† te a JSR instruction to an address 2 bytes
  14550. past the address in the A4 register. The ReadRest routine uses the registers as
  14551. follows:
  14552.  
  14553. Registers on entry to the ReadRest routine
  14554.  
  14555. A3                             Pointer to a buffer to hold the data you want to
  14556. read
  14557.  
  14558. D3                             Size of the buffer (word length); may be 0
  14559.  
  14560. Registers on exit from the ReadRest routine
  14561.  
  14562. A0                             Unchanged
  14563.  
  14564. A1                             Unchanged
  14565.  
  14566. A2                             Unchanged
  14567.  
  14568. A3                             Pointer to first byte after the last byte read
  14569. into buffer
  14570.  
  14571. D0                             Changed
  14572.  
  14573. D1                             Changed
  14574.  
  14575. D2                             Unchanged
  14576.  
  14577. D3                             Equals 0 if requested number of bytes were read;
  14578. less than 0 if
  14579.                                   more data was left than would fit in buffer
  14580.                                   (extra data equals –D3
  14581.                                   bytes); greater than 0 if less data was left
  14582.                                   than the size of the
  14583.                                   buffer (extra buffer space equals D3 bytes)
  14584.  
  14585. The ReadRest routine indicates an error by clearing to 0 the zero (z) flag in
  14586. the status register. 
  14587.  
  14588. You must terminate execution of your protocol handler with an RTS instruction
  14589. whether or not the ReadRest routine returns an error.
  14590.  
  14591. _______________________________________________________________________________
  14592.  
  14593. æKY .ENET…Driver…Routines
  14594. æC ».ENET Driver Routines                                                AppleTalk Manager
  14595. _______________________________________________________________________________
  14596.  
  14597. An application that uses AppleTalk Manager routines for network communications
  14598. can talk to whatever AppleTalk network the user has selected through the Network
  14599. control panel. However, you can choose to write an application that talks only
  14600. to Ethernet; in this case, your application has to address the Ethernet driver
  14601. directly. This section describes the functions that you can use to control the
  14602. .ENET driver, the Ethernet driver provided with system software version 7.0.
  14603. Each .ENET driver function is of the following form:
  14604.  
  14605. FUNCTION Efunc (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14606.  
  14607. The thePBptr parameter is a pointer to the .ENET parameter block and the async
  14608. parameter is a Boolean that specifies whether the function is to be executed
  14609. synchronously or asynchronously. Set the async parameter to TRUE to execute the
  14610. function asynchronously.
  14611.  
  14612. The .ENET parameter block is defined as follows:
  14613.  
  14614.    TYPE EParamBlock = 
  14615.         packed record
  14616.            qLink:         QElemPtr;         {next queue entry}
  14617.            qType:         Integer;          {queue type}
  14618.            ioTrap:        Integer;          {routine trap}
  14619.            ioCmdAddr:     Ptr;              {routine address}
  14620.            ioCompletion:  ProcPtr;          {completion   routine}
  14621.            ioResult:      OsErr;            {result code}
  14622.            ioNamePtr:     StringPtr;        {driver name}
  14623.            ioVRefNum:     Integer;          {volume reference number}
  14624.            ioRefNum:      Integer;          {driver reference number}
  14625.            csCode:        Integer;          {primary command code}
  14626.  
  14627.            CASE Integer OF
  14628.            ENetWrite,
  14629.            ENetAttachPH,
  14630.            ENetDetachPH,
  14631.            ENetRead,
  14632.            ENetRdCancel,
  14633.            ENetGetInfo,
  14634.            ENetSetGeneral:
  14635.            (
  14636.            eProtType:     Integer;          {Ethernet protocol type}
  14637.            ePointer:      Ptr;              {pointer; use depends on }
  14638.                                             { function}
  14639.            eBuffSize      Integer;          {buffer size}
  14640.            eDataSize      Integer           {number of bytes read}
  14641.            );
  14642.             
  14643.            ENetAddMulti,
  14644.            ENetDelMulti:
  14645.            (
  14646.            eMultiAddr:  ARRAY [0..5] of Char  {Multicast address}
  14647.            );
  14648.    END;
  14649.  
  14650. The qLink, qType, ioTrap, ioCmdAddr, ioNamePtr, and ioVRefNum fields are filled
  14651. in by the Device Manager; your application should not have to set or read these
  14652. fields. The ioResult field returns the result of the function. If you call the
  14653. function asynchronously, the function sets this field to 1 as soon as it begins
  14654. execution, and it changes the field to the actual result code when it completes
  14655. execution. The ioCompletion field is a pointer to a completion routine that you
  14656. can provide; the Device Manager calls your completion routine when it completes
  14657. execution of the function. If you are not providing a completion routine,
  14658. specify NIL for this field. You must obtain the driver reference number from the
  14659. OpenDriver function and use it for the ioRefNum field. 
  14660.  
  14661. The csCode field specifies the command to be executed; the MPW Pascal interface
  14662. fills in this field for you. The .ENET driver accepts the following constants as
  14663. routine selectors:
  14664.  
  14665. CONST  {.ENET driver routine selectors}
  14666.        ENetSetGeneral   = 253;  {Set "general" mode}
  14667.        ENetGetInfo      = 252;  {Get info}
  14668.        ENetRdCancel     = 251;  {Cancel read}
  14669.        ENetRead         = 250;  {Read}
  14670.        ENetWrite        = 249;  {Write}
  14671.        ENetDetachPH     = 248;  {Detach protocol handler}
  14672.        ENetAttachPH     = 247;  {Attach protocol handler}
  14673.        ENetAddMulti     = 246;  {Add a multicast address}
  14674.        ENetDelMulti     = 245;  {Delete a multicast address} 
  14675.  
  14676. The remaining parameters are used only for specific functions; all of these
  14677. parameters are described in the following sections.
  14678.  
  14679. For a general discussion of the use of the Ethernet driver, see “The .ENET
  14680. Driver” earlier in this chapter.
  14681.  
  14682. _______________________________________________________________________________
  14683.  
  14684. æKY Attaching…and…Detaching…an…Ethernet…Protocol…Handler
  14685. æC »Attaching and Detaching an Ethernet Protocol Handler                 AppleTalk Manager
  14686. _______________________________________________________________________________
  14687.  
  14688. The functions in this section allow you to attach a protocol handler to the
  14689. .ENET driver, to specify which protocol handler the .ENET driver is to use for
  14690. each protocol type, and to detach a protocol handler that you previously
  14691. attached. The section “Using Your Own Ethernet Protocol Handler to Read Data,”
  14692. earlier in this chapter, describes how to write and use Ethernet protocol
  14693. handlers.
  14694.  
  14695. FUNCTION EAttachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14696.  
  14697.    Parameter block
  14698.         ¨      16       ioResult           word         result code 
  14699.         Æ      26       csCode              word         always ENetAttachPH
  14700.         Æ      28       eProtType        word         Ethernet protocol type
  14701.         Æ      30       ePointer            long          pointer to protocol
  14702.         handler
  14703.  
  14704. The EAttachPH function serves two purposes: you can use it to attach to the
  14705. .ENET driver your own protocol handler for a specific protocol type, or you can
  14706. use it to specify that the .ENET driver should use the default protocol handler
  14707. for a particular protocol type. If you attach your own protocol handler, the
  14708. .ENET driver calls that protocol handler each time it receives a packet with the
  14709. protocol type you specified. If you specify that the .ENET driver should use the
  14710. default protocol handler, then you can use the ERead command to read packets
  14711. with that protocol type. 
  14712.  
  14713. The ioResult parameter returns the result of the function. If you call the
  14714. function asynchronously, the function sets this field to 1 as soon as it begins
  14715. execution, and it changes the field to the actual result code when it completes
  14716. execution. The csCode parameter is a routine selector; it is always equal to
  14717. ENetAttachPH for this function. 
  14718.  
  14719. You specify the protocol type in the eProtType parameter and provide a pointer
  14720. to the protocol handler in the ePointer parameter. If you specify NIL for the
  14721. ePointer parameter, then the .ENET driver uses the default protocol handler for
  14722. that protocol type. Specify 0 for the eProtType parameter to attach a protocol
  14723. handler for the IEEE 802.3 protocol, which uses protocol types 0 through $5DC.
  14724.  
  14725.    Note:  The LAP Manager calls the EAttachPH function with a protocol type of 0
  14726.    and thus receives all 802.3 protocol packets. Instead of using the EAttachPH
  14727.    function to install a protocol handler for an 802.3 Ethernet protocol type,
  14728.    you
  14729.    should use the L802Attach routine. In the case of an 802.3 protocol packet,
  14730.    the
  14731.    .ENET driver passes the packet to the LAP Manager 802.2 protocol handler. If
  14732.    the
  14733.    packet has the protocol type you specified with the L802Attach routine, the
  14734.    802.2
  14735.    protocol handler passes the packet on to your protocol handler. For more
  14736.    information about IEEE 802.2 and 802.3 protocols, see “The LAP Manager 802.2
  14737.    Protocol” earlier in this chapter.
  14738.  
  14739.    Result codes
  14740.           noErr                    0           No error
  14741.           LAPProtErr     –94           Protocol handler is already attached or
  14742.           node’s protocol
  14743.                                                       table is full
  14744.  
  14745. FUNCTION EDetachPH (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14746.  
  14747.    Parameter block
  14748.             ¨       16        ioResult           word          result code 
  14749.             Æ       26        csCode              word          always
  14750.             ENetDetachPH
  14751.             Æ       28        eProtType        word         Ethernet protocol
  14752.             type
  14753.  
  14754. The EDetachPH function detaches a protocol handler from the .ENET driver. Once
  14755. you have removed a protocol type from the node’s protocol table with this
  14756. function, the .ENET driver no longer delivers packets with that protocol type.
  14757. You specify the protocol type in the eProtType parameter.
  14758.  
  14759. The ioResult parameter returns the result of the function. If you call the
  14760. function asynchronously, the function sets this field to 1 as soon as it begins
  14761. execution, and it changes the field to the actual result code when it completes
  14762. execution. The csCode parameter is a routine selector that is set automatically
  14763. for you by the MPW interface; it is always equal to ENetDetachPH for this
  14764. function. 
  14765.  
  14766. When you call the EDetachPH function, any pending calls to the ERead function
  14767. terminate with the reqAborted result code.
  14768.  
  14769.    Result codes
  14770.           noErr                        0           No error
  14771.           LAPProtErr          –94          No protocol handler is attached
  14772. _______________________________________________________________________________
  14773.  
  14774. æKY Writing…and…Reading…Ethernet…Packets
  14775. æC »Writing and Reading Ethernet Packets                                 AppleTalk Manager
  14776. _______________________________________________________________________________
  14777.  
  14778. The functions in this section send and read Ethernet packets, cancel execution
  14779. of a read operation, return information about the .ENET driver, and switch the
  14780. .ENET driver from limited-transmission mode to general-transmission mode. 
  14781.  
  14782. FUNCTION EWrite (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr; 
  14783.  
  14784.    Parameter block
  14785.         ¨       16       ioResult        word         result code 
  14786.         Æ       26       csCode           word         always ENetWrite
  14787.         Æ       30       ePointer         long          pointer to write-data
  14788.         structure
  14789.  
  14790. The EWrite function uses the .ENET driver to send a data packet over Ethernet.
  14791. You must first prepare a write-data structure that specifies the destination
  14792. address and the protocol type and contains the data that you want to send. You
  14793. place a pointer to the write-data structure in the ePointer parameter. If you
  14794. want to send a packet larger than 768 bytes, you must first call the ESetGeneral
  14795. function to put the .ENET driver in general transmission mode. If the size of
  14796. the packet you provide is less than 60 bytes, the driver adds pad bytes to the
  14797. packet. Write-data structures are described in “Using a Write-Data Structure to
  14798. Transmit Ethernet Data” earlier in this chapter.
  14799.  
  14800. The ioResult parameter returns the result of the function. If you call the
  14801. function asynchronously, the function sets this field to 1 as soon as it begins
  14802. execution, and it changes the field to the actual result code when it completes
  14803. execution. The csCode parameter is a routine selector that is set automatically
  14804. for you by the MPW interface; it is always equal to ENetWrite for this function.
  14805.  
  14806.  
  14807.    Result codes
  14808.           noErr                       0          No error
  14809.           eLenErr               –92          Packet too large or first entry of
  14810.           the
  14811.                                                         write-data-structure did
  14812.                                                         not contain the full
  14813.                                                         14-byte
  14814.                                                         header
  14815.           excessCollsns     –95          Hardware error
  14816.  
  14817. FUNCTION ERead (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14818.  
  14819. Parameter block
  14820.       ¨       16       ioResult             word              result code 
  14821.       Æ       26       csCode                word              always ENetRead
  14822.       Æ       28       eProtType          word              Ethernet protocol
  14823.       type
  14824.       Æ       30       ePointer              long              pointer to data
  14825.       buffer
  14826.       Æ       34       eBuffSize            word            size of data buffer
  14827.       ¨       36       eDataSize           word             number of bytes read
  14828.  
  14829. The ERead function uses the default protocol handler to read a data packet and
  14830. place it in a data buffer. You can use the ERead function to read packets of a
  14831. particular protocol type only after you have used the EAttachPH function to
  14832. specify a NIL pointer to the protocol handler for that protocol type.
  14833.  
  14834. The ioResult parameter returns the result of the function. If you call the
  14835. function asynchronously, the function sets this field to 1 as soon as it begins
  14836. execution, and it changes the field to the actual result code when it completes
  14837. execution. The csCode parameter is the routine selector, automatically set by
  14838. the MPW interface. It is always ENetRead for this function. 
  14839.  
  14840. The eProtType parameter specifies the protocol type of the packet you want to
  14841. read. The ePointer parameter is a pointer to the data buffer into which you want
  14842. to read data, and the eBuffSize parameter indicates the size of the data buffer.
  14843. If you are expecting EtherTalk data packets, the buffer should be at least 621
  14844. bytes in size; if you are expecting general Ethernet data packets, the buffer
  14845. should be at least 1514 bytes in size. 
  14846.  
  14847. The ERead function places the entire packet, including the packet header, into
  14848. your buffer. The function returns in the eDataSize parameter the number of bytes
  14849. actually read. If the packet is larger than the data buffer, the ERead function
  14850. places as much of the packet as will fit into the buffer and returns the
  14851. buf2SmallErr result code.
  14852.  
  14853. Call the ERead function asynchronously to await the next data packet. When the
  14854. .ENET driver receives the data packet, it completes execution of the ERead
  14855. function and calls your completion routine. If the .ENET driver receives a data
  14856. packet with a protocol type for which you specified the default protocol handler
  14857. while no ERead command is pending, the driver discards the data packet.
  14858.  
  14859. You can have several asynchronous calls to the ERead function pending execution
  14860. simultaneously, as long as you use a different parameter block for each call.
  14861.  
  14862.    Result codes
  14863.           noErr                            0         No error
  14864.           LAPProtErr             –94         Protocol not attached or protocol
  14865.           handler pointer
  14866.                                                             was not 0
  14867.           buf2SmallErr       –3101        Packet too large for buffer; partial
  14868.           data returned
  14869.           reqAborted           –1105        ERdCancel or EDetachPH function
  14870.           called
  14871.  
  14872. FUNCTION ERdCancel (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14873.  
  14874.    Parameter block
  14875.        ¨       16       ioResult         word          result code 
  14876.        Æ       26       csCode            word          always ENetRdCancel
  14877.        Æ       30       ePointer         long           pointer to ERead
  14878.        parameter block
  14879.  
  14880. The ERdCancel function cancels execution of a specific call to the ERead
  14881. function. You must have called the ERead function asynchronously to use the
  14882. ERdCancel function. You specify in the ePointer parameter a pointer to the
  14883. parameter block that you used when you called the ERead function. 
  14884.  
  14885. The ioResult parameter returns the result of the function. If you call the
  14886. function asynchronously, the function sets this field to 1 as soon as it begins
  14887. execution, and it changes the field to the actual result code when it completes
  14888. execution. The csCode parameter is the routine selector, automatically set by
  14889. the MPW interface. It is always ENetRdCancel for this function. 
  14890.  
  14891. When you call the ERdCancel function, the pending ERead function that you cancel
  14892. receives the reqAborted result code.
  14893.  
  14894.    Result codes
  14895.           noErr                          0              No error
  14896.           cbNotFound      –1102             ERead not active
  14897.  
  14898. FUNCTION EGetInfo (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14899.  
  14900.    Parameter block
  14901.         ¨           16         ioResult          word          result code 
  14902.         Æ     26         csCode             word          always ENetGetInfo
  14903.         Æ     30         ePointer           long          pointer to buffer
  14904.         Æ     34         eBuffSize         word         size of buffer
  14905.  
  14906. The EGetInfo function returns information about the .ENET driver. Before calling
  14907. this function, you must allocate a data buffer of at least 18 bytes. Put a
  14908. pointer to the buffer in the ePointer parameter and the size of the buffer in
  14909. the eBuffSize parameter.
  14910.  
  14911. The EGetInfo function places the following information in the data buffer:
  14912.  
  14913.    Bytes               Information
  14914.  
  14915.    1–6                   Ethernet address of the node on which the driver is
  14916.    installed
  14917.    7–10                 Number of times the receive queue has overflowed
  14918.    11–14               Number of data transmission operations that have timed
  14919.    out 
  14920.    15–18               Number of packets received that contain an incorrect
  14921.    address 
  14922.  
  14923. An incorrect Ethernet address is one that is neither the broadcast address, a
  14924. multicast address for which this node is registered, nor the node’s data link
  14925. address. A node could receive an incorrect Ethernet address due to a hardware or
  14926. software error.
  14927.  
  14928. The ioResult parameter returns the result of the function. If you call the
  14929. function asynchronously, the function sets this field to 1 as soon as it begins
  14930. execution, and it changes the field to the actual result code when it completes
  14931. execution. The csCode parameter is the routine selector, automatically set by
  14932. the MPW interface. It is always ENetGetInfo for this function.  
  14933.  
  14934.    Result code
  14935.           noErr         0          No error
  14936.  
  14937. FUNCTION ESetGeneral (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14938.  
  14939.    Parameter block
  14940.          ¨      16        ioResult        word           result code 
  14941.          Æ      26        csCode           word           always ENetSetGeneral
  14942.  
  14943. The ESetGeneral function switches the .ENET driver from limited-transmission
  14944. mode to general-transmission mode. In limited-transmission mode, the .ENET
  14945. driver allocates a write-data buffer of 768 bytes. This buffer size is more than
  14946. sufficient to hold an EtherTalk data packet, which can be no larger than 621
  14947. bytes. In general-transmission mode, the .ENET driver can transmit an Ethernet
  14948. data packet of up to 1514 bytes.
  14949.  
  14950. The ioResult parameter returns the result of the function. If you call the
  14951. function asynchronously, the function sets this field to 1 as soon as it begins
  14952. execution, and it changes the field to the actual result code when it completes
  14953. execution. The csCode parameter is the routine selector, automatically set by
  14954. the MPW interface. It is always ENetSetGeneral for this function.  
  14955.  
  14956. There is no command to switch the .ENET driver from general-transmission mode to
  14957. limited-transmission mode. To switch back to limited-transmission mode, you have
  14958. to reset the driver by restarting the computer.
  14959.  
  14960.    Result codes
  14961.           noErr                           0             No error
  14962.           memFullErr        –108             Insufficient memory in heap
  14963. _______________________________________________________________________________
  14964.  
  14965. æKY Adding…and…Removing…Ethernet…Multicast…Addresses
  14966. æC »Adding and Removing Ethernet Multicast Addresses                     AppleTalk Manager
  14967. _______________________________________________________________________________
  14968.  
  14969. The functions in this section add or delete Ethernet multicast addresses for a
  14970. particular node. A multicast address is an Ethernet address for which the node
  14971. accepts packets just as it does for its permanently assigned Ethernet hardware
  14972. address. In a multicast address, the low-order bit of the high-order byte is set
  14973. to 1. Each node can have any number of multicast addresses, and any number of
  14974. nodes can have the same multicast address. The purpose of a multicast address is
  14975. to allow a group of Ethernet nodes to receive the same transmission
  14976. simultaneously, in a fashion similar to the AppleTalk broadcast service.
  14977.  
  14978. FUNCTION EAddMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  14979.  
  14980.    Parameter block
  14981.         ¨      16        ioResult                  word              result code
  14982.  
  14983.         Æ      26        csCode                     word              always
  14984.         ENetAddMulti
  14985.         Æ      28        eMultiAddr           6 bytes           multicast
  14986.         address
  14987.  
  14988. The EAddMulti function adds a multicast address to the node on which the .ENET
  14989. driver is running. 
  14990.  
  14991. You must provide (in the eMultiAddr parameter) the multicast address that you
  14992. want to use. Each time a client of the .ENET driver calls the EAddMulti function
  14993. for a particular multicast address, the driver increments a counter for that
  14994. multicast address. Each time a client of the .ENET driver calls the EDelMulti
  14995. function, the driver decrements the counter for that address. As long as the
  14996. count for a multicast address is equal to or greater than 1, the .ENET driver
  14997. accepts packets directed to that multicast address. Therefore, if any client of
  14998. the .ENET driver in the node has called the EAddMulti function for a particular
  14999. multicast address, the driver receives packets delivered to that address.
  15000.  
  15001. The ioResult parameter returns the result of the function. If you call the
  15002. function asynchronously, the function sets this field to 1 as soon as it begins
  15003. execution, and it changes the field to the actual result code when it completes
  15004. execution. The csCode parameter is the routine selector, automatically set by
  15005. the MPW interface. It is always ENetAddMulti for this function. 
  15006.  
  15007.    Result codes
  15008.           noErr                       0             No error
  15009.           eMultiErr           –91             Invalid address or table is full 
  15010.  
  15011. FUNCTION EDelMulti (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15012.  
  15013.    Parameter block
  15014.         ¨        16        ioResult              word           result code 
  15015.         Æ        26        csCode                 word           always
  15016.         ENetDelMulti
  15017.         Æ         28        eMultiAddr       6 bytes         multicast address
  15018.  
  15019. The EDelMulti function decrements the counter kept by the .ENET driver for a
  15020. particular multicast address. Each time a client of the .ENET driver calls the
  15021. EAddMulti function, the driver increments a counter for the multicast address
  15022. specified by the eMultiAddr parameter. Each time a client of the .ENET driver
  15023. calls the EDelMulti function, the driver decrements the counter for the address
  15024. specified by the eMultiAddr parameter. As long as the count for a multicast
  15025. address is equal to or greater than 1, the .ENET driver accepts packets directed
  15026. to that multicast address. When the count for an address equals 0, the driver
  15027. removes that address from the list of multicast addresses that it accepts.
  15028.  
  15029.    Note:  Because more than one client of the .ENET driver might be using a
  15030.    particular multicast address, you should call the EDelMulti function only
  15031.    once for
  15032.    each time you called the EAddMulti function.
  15033.  
  15034. The ioResult parameter returns the result of the function. If you call the
  15035. function asynchronously, the function sets this field to 1 as soon as it begins
  15036. execution, and it changes the field to the actual result code when it completes
  15037. execution. The csCode parameter is the routine selector, automatically set by
  15038. the MPW interface. It is always ENetDelMulti for this function.  
  15039.  
  15040.    Result codes
  15041.           noErr                         0                  No error
  15042.           eMultiErr              –91'                Address not found
  15043. _______________________________________________________________________________
  15044.  
  15045. æKY Summary…of…the…Appletalk…Manager…Volume…VI
  15046. æC »Summary of the Appletalk Manager Volume VI                           AppleTalk Manager
  15047. _______________________________________________________________________________
  15048.  
  15049. Click the arrow in the lower-right corner of this window to see the summary
  15050. sections of the constants, datatypes, and routines for the AppleTalk Manager.
  15051.  
  15052. _______________________________________________________________________________
  15053.  
  15054. æKY Appletalk…Manager…Constants
  15055. æC »Appletalk Manager Constants                                          AppleTalk Manager
  15056. _______________________________________________________________________________
  15057.  
  15058. const
  15059.         {AppleTalk transitions}
  15060.         ATTransOpen             = 0;    {open transition}
  15061.         ATTransClose            = 2;    {prepare-to-close transition}
  15062.         ATTransClosePrep        = 3;    {permission-to-close transition}
  15063.         ATTransCancelClose      = 4;    {cancel-close transition}
  15064.  
  15065.         {.XPP driver routine selector}
  15066.         xCall                = 246;
  15067.  
  15068.         {.XPP driver routine selector subcodes}
  15069.         zipGetLocalZones       = 5;
  15070.         zipGetZoneList         = 6;
  15071.         zipGetMyZone           = 7;
  15072.  
  15073.         {ADSP routine selectors}
  15074.         dspInit               = 255;    {create a new connection end}
  15075.         dspRemove             = 254;    {remove a connection end}
  15076.         dspOpen               = 253;    {open a connection}
  15077.         dspClose              = 252;    {close a connection}
  15078.         dspCLInit             = 251;    {create a connection listener}
  15079.         dspCLRemove           = 250;    {remove a connection listener}
  15080.         dspCLListen           = 249;    {post a listener request}
  15081.         dspCLDeny             = 248;    {deny an open-connection request}
  15082.         dspStatus             = 247;    {get status of connection end}
  15083.         dspRead               = 246;    {read data from the connection}
  15084.         dspWrite              = 245;    {write data on the connection}
  15085.         dspAttention          = 244;    {send an attention message}
  15086.         dspOptions            = 243;    {set connection end options}
  15087.         dspReset              = 242;    {forward reset the connection}
  15088.         dspNewCID             = 241;    {generate a cid for a connection end}
  15089.  
  15090.         {ADSP connection opening modes}
  15091.         ocRequest               = 1;    {request a connection with remote}
  15092.         ocPassive               = 2;    {wait for a connection request from }
  15093.                                         { remote connection end}
  15094.         ocAccept                = 3;    {accept request as delivered by
  15095.                                          listener}
  15096.         ocEstablish             = 4;    {consider connection to be open}
  15097.  
  15098.         {ADSP connection end states}
  15099.         sListening              = 1;    {for connection listeners}
  15100.         sPassive                = 2;    {waiting for a connection request
  15101.                                          from }
  15102.                                         { remote connection end}
  15103.         sOpening                = 3;    {requesting a connection with remote}
  15104.         sOpen                   = 4;    {connection is open}
  15105.         sClosing                = 5;    {connection is being torn down}
  15106.         sClosed                 = 6;    {connection end state is closed}
  15107.  
  15108.         {ADSP client event flags}
  15109.         eClosed               = $80;    {received connection closed advice}
  15110.         eTearDown             = $40;    {closed due to broken connection}
  15111.         eAttention            = $20;    {received attention message}
  15112.         eFwdReset             = $10;    {received forward reset advice}
  15113.  
  15114.         {miscellaneous ADSP constants}
  15115.         attnBufSize           = 570;    {size of client attention buffer}
  15116.         minDSPQueueSize       = 100;    {minimum size of receive or send
  15117.                                          queue}
  15118.  
  15119.          {.ENET driver values}
  15120.          catNetwork             = 4;    {spCategory for EtherTalk NB card}
  15121.          typeEtherNet           = 1;    {spCType for EtherTalk NB card}
  15122.  
  15123.          {LAP Manager values}
  15124.          LAPMgrCall             = 2;    {Offset to LAP routines}
  15125.          LAddAEQ               = 23;    {LAPAddATQ routine selector}
  15126.          LRmvAEQ               = 24;    {LAPRmvATQ routine selector}
  15127.  
  15128.          {.ENET driver routine selectors}
  15129.          ENetSetGeneral       = 253;    {Set "general" mode}
  15130.          ENetGetInfo          = 252;    {Get info}
  15131.          ENetRdCancel         = 251;    {Cancel read}
  15132.          ENetRead             = 250;    {Read}
  15133.          ENetWrite            = 249;    {Write}
  15134.          ENetDetachPH         = 248;    {Detach protocol handler}
  15135.          ENetAttachPH         = 247;    {Attach protocol handler}
  15136.          ENetAddMulti         = 246;    {Add a multicast address}
  15137.          ENetDelMulti         = 245;    {Delete a multicast address}
  15138.  
  15139. _______________________________________________________________________________
  15140.  
  15141. æKY Appletalk…Manager…Data…Types
  15142. æC »Appletalk Manager Data Types                                         AppleTalk Manager
  15143. _______________________________________________________________________________
  15144.  
  15145. TYPE ATQentry = 
  15146.      RECORD
  15147.         qLink:       ATQentryPtr;   {next queue entry}
  15148.         qType:       Integer;       {reserved}
  15149.         CallAddr:    ProcPtr;       {pointer to your routine}
  15150.      END;
  15151.      ATQentryptr = ^ATQentry;
  15152.  
  15153.      ATPParamBlock = 
  15154.      PACKED RECORD                  {extended parameter block for }
  15155.                                     { PSendRequest and PNSendRequest}
  15156.         qLink:          QElemPtr;   {next queue entry}
  15157.         qType:          Integer;    {queue type}
  15158.         ioTrap:         Integer;    {routine trap}
  15159.         ioCmdAddr:      Ptr;        {routine address}
  15160.         ioCompletion:   ProcPtr;    {completion routine}
  15161.         ioResult:       OsErr;      {result code}
  15162.         userData:       LongInt;    {ATP user bytes}
  15163.         reqTID:         Integer;    {request transaction ID}
  15164.         ioRefNum:       Integer;    {driver reference number}
  15165.         csCode:         Integer;    {primary command code}
  15166.         atpSocket:      Byte;       {currBitMap or socket number}
  15167.         atpFlags:       Byte;       {control information - set bit 2 }
  15168.                                     { for extended parameter block}
  15169.         addrBlock:      AddrBlock;  {source socket address}
  15170.         reqLength:      Integer;    {request size in bytes}
  15171.         reqPointer:     Ptr;        {pointer to request data}
  15172.         bdsPointer:     Ptr;        {pointer to response Buffer }
  15173.                                     { Data Structure}
  15174.         numOfBuffs:     Byte;       {number of responses expected}
  15175.         timeOutVal:     Byte;       {timeout interval}
  15176.         numOfResps:     Byte;       {number of responses }
  15177.                                     { actually received}
  15178.         retryCount:     Byte;       {number of retries}
  15179.         intBuff:        Integer;    {used internally for NSendRequest}
  15180.         TRelTime:       Byte        {release timer setting}
  15181.  
  15182. END;
  15183.  
  15184.      XPPParamBlock = 
  15185.      PACKED RECORD
  15186.         qLink:          QElemPtr;   {next queue entry}
  15187.         qType:          Integer;    {queue type}
  15188.         ioTrap:         Integer;    {routine trap}
  15189.         ioCmdAddr:      Ptr;        {routine address}
  15190.         ioCompletion:   ProcPtr;    {completion routine}
  15191.         ioResult:       OsErr;      {result code}
  15192.         cmdResult:      LongInt;    {command result}
  15193.         ioVRefNum:      Integer;    {volume reference number}
  15194.         ioRefNum:       Integer;    {driver reference number}
  15195.         csCode:         Integer;    {primary command code}
  15196.         CASE XPPPrmBlkType OF
  15197.           xCallParam
  15198.             xppSubCode:    Integer;  {secondary command code}
  15199.             xppTimeOut:    Byte;     {timeout period for .XPP}
  15200.             xppRetry:      Byte;     {retry count}
  15201.             filler1:       Integer;  {reserved}
  15202.             zipBuffPtr:    Ptr;      {returned zone names}
  15203.             zipNumZones:   Integer;  {number of zones returned}
  15204.             zipLastFlag:   Byte;     {nonzero when all zone }
  15205.                                      { names have been returned}
  15206.             filler2  Byte;  {reserved}
  15207.             zipInfoField: packed array[1..70] of Byte
  15208.                                      {reserved for use by .XPP}
  15209. END;
  15210. XPPParmBlkPtr = ^XPPParamBlock;
  15211.  
  15212. TRCCB = 
  15213. PACKED RECORD
  15214.    ccbLink:                TPCCB;        {link to next CCB}
  15215.    refNum:                 Integer;      {reference number}
  15216.    state:                  Integer;      {state of the connection end}
  15217.    userFlags:              Byte;         {user flags for connection}
  15218.    localSocket:            Byte;         {local socket number}
  15219.    remoteAddress:          AddrBlock;    {remote end internet address}
  15220.    attnCode:               Integer;      {attention code received}
  15221.    attnSize:               Integer;      {size of attention data}
  15222.    attnPtr:                Ptr;          {pointer to attention data}
  15223.    reserved:               PACKED ARRAY [1..220] OF Byte
  15224.                            {reserved for use by ADSP}
  15225. END;
  15226.  
  15227. AddrBlock = 
  15228. PACKED RECORD
  15229.    aNet:                   Integer;      {network number}
  15230.    aNode:                  Byte;         {node ID}
  15231.    aSocket:                Byte;         {socket number}
  15232. END;
  15233.  
  15234. DSPParamBlock = 
  15235. PACKED RECORD
  15236.    qLink:                  QElemPtr;     {next queue entry}
  15237.    qType:                  Integer;      {queue type}
  15238.    ioTrap:                 Integer;      {routine trap}
  15239.    ioCmdAddr:              Ptr;          {routine address}
  15240.    ioCompletion:           ProcPtr;      {completion routine}
  15241.    ioResult:               OsErr;        {result code}
  15242.    ioNamePtr:              StringPtr;    {reserved}
  15243.    ioVRefNum:              Integer;      {reserved}
  15244.    ioCRefNum:              Integer;      {driver reference number}
  15245.    csCode:                 Integer;      {primary command code}
  15246.    qStatus:                LongInt;      {reserved for ADSP}
  15247.    ccbRefNum:              Integer;      {CCB reference number}
  15248.  
  15249.    CASE Integer OF
  15250.    dspInit,
  15251.    dspCLInit:
  15252.    (
  15253.       ccbPtr:              TPCCB;        {pointer to CCB}
  15254.       userRoutine:         ProcPtr;      {pointer to user routine}
  15255.       sendQSize:           Integer;      {size of send queue}
  15256.       sendQueue:           Ptr;          {pointer to send queue}
  15257.       recvQSize:           Integer;      {size of receive queue}
  15258.       recvQueue:           Ptr;          {pointer to receive queue}
  15259.       attnPtr:             Ptr;          {pointer to attention- }
  15260.                                          { message buffer}
  15261.       localSocket:         Byte;         {local socket number}
  15262.       filler1:             Byte;         {filler for proper alignment}
  15263.     );
  15264.  
  15265.     dspOpen,
  15266.     dspCLListen,
  15267.     dspCLDeny:
  15268.   (
  15269.       localCID:            Integer;      {local connection ID}
  15270.       remoteCID:           Integer;      {remote connection ID}
  15271.       remoteAddress:       AddrBlock;    {remote internet address}
  15272.       filterAddress:       AddrBlock;    {address filter}
  15273.       sendSeq:             LongInt;      {send sequence number}
  15274.       sendWindow:          Integer;      {size of remote buffer}
  15275.       recvSeq:             LongInt;      {receive sequence number}
  15276.       attnSendSeq:         LongInt;      {attention send seq number}
  15277.       attnRecvSeq:         LongInt;      {attention receive seq num}
  15278.       ocMode:              Byte;         {connection opening mode}
  15279.       ocInterval:          Byte;         {interval bet open requests}
  15280.       ocMaximum:           Byte;         {retries of open conn req}
  15281.       filler2:             Byte;         {filler for proper alignment}
  15282.     );
  15283.   
  15284.     dspClose,
  15285.     dspRemove:
  15286.    (
  15287.       abort:               Byte;         {abort send requests}
  15288.       filler3:             Byte;         {filler for proper alignment}
  15289.    );
  15290.   
  15291.    dspStatus:
  15292.    (
  15293.       statusCCB:            TPCCB;       {pointer to CCB}
  15294.       sendQPending:         Integer;     {bytes waiting in send queue}
  15295.       sendQFree:            Integer;     {available send-queue buffer}
  15296.       recvQPending:         Integer;     {bytes in receive queue}
  15297.       recvQFree:            Integer;     {avail receive-queue buffer}
  15298.    )
  15299.   
  15300.    dspRead,
  15301.    dspWrite:
  15302.    (
  15303.       reqCount:             Integer;     {requested number of bytes}
  15304.       actCount:             Integer;     {actual number of bytes}
  15305.       dataPtr:              Ptr;         {pointer to data buffer}
  15306.       eom:                  Byte;        {1 if end of message}
  15307.       flush:                Byte;        {1 to send data now}
  15308.    )
  15309.   
  15310.    dspAttention:
  15311.    (
  15312.       attnCode:             Integer;     {client attention code}
  15313.       attnSize:             Integer;     {size of attention data}
  15314.       attnData:             Ptr;         {pointer to attention data}
  15315.       attnInterval:         Byte;        {reserved}
  15316.       filler4:              Byte;        {filler for proper alignment}
  15317.    )
  15318.   
  15319.    dspOptions:
  15320.    (
  15321.       sendBlocking:         Integer;     {send-blocking threshold}
  15322.       sendTimer:            Byte;        {reserved}
  15323.       rtmtTimer:            Byte;        {reserved}
  15324.       badSeqMax:            Byte;        {retransmit advice threshold}
  15325.       useCheckSum:          Byte;        {DDP checksum for packets}
  15326.    )
  15327.   
  15328.    dspNewCID:
  15329.    (
  15330.       newCID:               Integer      {new connection ID}
  15331.    )
  15332. END;
  15333.  
  15334. EParamBlock = 
  15335. PACKED RECORD
  15336.    qLink:           QElemPtr;         {next queue entry}
  15337.    qType:           Integer;          {queue type}
  15338.    ioTrap:          Integer;          {routine trap}
  15339.    ioCmdAddr:       Ptr;              {routine address}
  15340.    ioCompletion:    ProcPtr;          {completion routine}
  15341.    ioResult:        OsErr;            {result code}
  15342.    ioNamePtr:       StringPtr;        {driver name}
  15343.    ioVRefNum:       Integer;          {volume reference number}
  15344.    ioRefNum:        Integer;          {driver reference number}
  15345.    csCode:          Integer;          {primary command code}
  15346.   
  15347.    CASE Integer OF
  15348.    ENetWrite,
  15349.    ENetAttachPH,
  15350.    ENetDetachPH,
  15351.    ENetRead,
  15352.    ENetRdCancel,
  15353.    ENetGetInfo,
  15354.    ENetSetGeneral:
  15355.    (
  15356.    eProtType:       Integer;          {Ethernet protocol type}
  15357.    ePointer:        Ptr;              {pointer; use depends on }
  15358.                                       { function}
  15359.    eBuffSize        Integer;          {buffer size}
  15360.    eDataSize        Integer           {number of bytes read}
  15361.    );
  15362.    ENetAddMulti,
  15363.    ENetDelMulti:
  15364.    (
  15365.    eMultiAddr:  ARRAY [0..5] of Char  {Multicast address}
  15366.    );
  15367. END;
  15368. EParamBlkPtr = ^EParamBlock;
  15369. _______________________________________________________________________________
  15370.  
  15371. æKY Appletalk…Manager…Routines…Summary
  15372. æC »Appletalk Manager Routines Summary                                   AppleTalk Manager
  15373. _______________________________________________________________________________
  15374.  
  15375. Getting Information About the .MPP Driver
  15376.  
  15377. FUNCTION PGetAppleTalkInfo  (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  15378.  
  15379.  
  15380. Adding and Removing AppleTalk Transition Queue Entries
  15381.  
  15382. FUNCTION LAPAddATQ  (theATQEntry: ATQEntryPtr): OSErr;
  15383.  
  15384. FUNCTION LAPRmvATQ  (theATQEntry: ATQEntryPtr): OSErr;
  15385.  
  15386.  
  15387. Sending Messages to the AppleTalk Transition Queue
  15388.  
  15389. FUNCTION PATalkClosePrep  (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  15390.  
  15391.  
  15392. Defining Your Own AppleTalk Transition 
  15393.  
  15394. PROCEDURE ATEvent  (event: LongInt; infoPtr: Ptr);
  15395.  
  15396. FUNCTION ATPreFlightEvent  (event,cancel: LongInt; infoPtr: Ptr) : OSErr;
  15397.  
  15398.  
  15399. Canceling All Calls to the ATPGetRequest Function
  15400.  
  15401. FUNCTION ATPKillAllGetReq  (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  15402.  
  15403.  
  15404. Obtaining Zone Information
  15405.  
  15406. FUNCTION GetMyZone  (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  15407.  
  15408. FUNCTION GetLocalZones  (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  15409.  
  15410. FUNCTION GetZoneList  (thePBptr: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  15411.  
  15412.  
  15413. Attaching and Detaching an Ethernet Protocol Handler
  15414.  
  15415. FUNCTION EAttachPH  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15416.  
  15417. FUNCTION EDetachPH  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15418.  
  15419.  
  15420. Writing and Reading Ethernet Packets
  15421.  
  15422. FUNCTION EWrite  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15423.  
  15424. FUNCTION ERead  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15425.  
  15426. FUNCTION ERdCancel  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15427.  
  15428. FUNCTION EGetInfo  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15429.  
  15430. FUNCTION ESetGeneral  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15431.  
  15432.  
  15433. Adding and Removing Ethernet Multicast Addresses
  15434.  
  15435. FUNCTION EAddMulti  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15436.  
  15437. FUNCTION EDelMulti  (thePBptr: EParamBlkPtr; async: BOOLEAN) : OSErr;
  15438. _______________________________________________________________________________
  15439.  
  15440. æKY Appletalk…Manager…Global…Variable
  15441. æC »Appletalk Manager Global Variable                                    AppleTalk Manager
  15442. _______________________________________________________________________________
  15443.  
  15444. LapMgrPtr                  The start of the LAP Manager
  15445.  
  15446. _______________________________________________________________________________
  15447.  
  15448. æKY Appletalk…Manager…Result…Codes
  15449. æC »Appletalk Manager Result Codes                                       AppleTalk Manager
  15450. _______________________________________________________________________________
  15451.  
  15452. noErr                                0            no error
  15453. qErr                                 –1            Queue element not found
  15454. closeErr                        –24            permission to close .MPP driver
  15455. was denied
  15456. paramErr                     –50            Version number is too high
  15457. ddpSktErr                    –91            error opening socket
  15458. eMultiErr                    –91            invalid address, address not found,
  15459. or table is full 
  15460. eLenErr                        –92            packet too large or first entry of
  15461. the write-data
  15462.                                                          structure did not
  15463.                                                          contain the full
  15464.                                                          14-byte header
  15465. noBridgeErr                –93            no router is available
  15466. LAPProtErr                 –94            protocol handler is already attached,
  15467. node’s protocol 
  15468.                                                          table is full, no
  15469.                                                          protocol handler is
  15470.                                                          attached, or
  15471.                                                          protocol handler
  15472.                                                          pointer was not 0
  15473. excessCollsns             –95             hardware error
  15474. memFullErr             –108             Insufficient memory in heap
  15475. reqFailed                 –1096             request to contact router failed;
  15476. retry count exceeded 
  15477. cbNotFound           –1102             control block not found, no pending
  15478. asynchronous
  15479.                                                            calls, or ERead not
  15480.                                                            active
  15481. reqAborted               –1105             ERdCancel or EDetachPH function
  15482. called
  15483. errOpenDenied       –1273             open request denied by recipient
  15484. errDSPQueueSize   –1274             send or receive queue is too small
  15485. errFwdReset             –1275            read terminated by forward reset
  15486. errAttention             –1276            attention message too long
  15487. errOpening               –1277             attempt to open connection failed
  15488. errState                      –1278             bad connection state for this
  15489. operation
  15490. errAborted                –1279             request aborted by dspRemove or
  15491. dspClose routine
  15492. errRefNum              –1280              bad connection reference number
  15493. buf2SmallErr            –3101             packet too large for buffer; partial
  15494. data returned
  15495. _______________________________________________________________________________
  15496.  
  15497. æKY Appletalk…Manager…Assembly-language…Information
  15498. æC »Appletalk Manager Assembly-language Information                      AppleTalk Manager
  15499. _______________________________________________________________________________
  15500.  
  15501. Constants
  15502.  
  15503. ;ADSP queue element equates & size
  15504. csQStatus     .EQU      CSParam        ;adsp internal use
  15505. csCCBRef      .EQU      csQStatus+4    ;refnum of ccb
  15506.  
  15507.  
  15508. AppleTalk Transition Queue Entry Data Structure
  15509.  
  15510. AeQQLink         long             next queue entry
  15511. AeQQType        word             reserved
  15512. AeQCallAddr   long              pointer to your routine
  15513.   
  15514.  
  15515. ADSP Connection Control Block Data Structure
  15516.  
  15517. ccbLink                   long             link to next CCB
  15518. refNum                 word            reference number
  15519. state                        word            state of the connection end
  15520. userFlags                byte             user flags for connection
  15521. localSocket             byte             local socket number
  15522. remoteAddress     long             internet address of remote end
  15523. attnCode                word            attention code received
  15524. attnSize                  word           size of received attention data
  15525. attnPtr                    long             pointer to received attention data
  15526. reserved                 220 bytes     reserved
  15527.  
  15528.  
  15529. XPP Parameter Block xCallParam Variant
  15530.  
  15531.       ¨          16         ioResult                  word          result code 
  15532.       Æ          26         csCode                     word          routine
  15533.       selector; always xCall
  15534.       Æ          28         xppSubCode           word          routine selector
  15535.       subcode
  15536.       Æ          30         xppTimeOut           byte            retry interval
  15537.       in seconds
  15538.       Æ          31         xppRetry                  byte            retry
  15539.       count
  15540.       Æ          34         zipBuffPtr                long           pointer to
  15541.       data buffer
  15542.       ¨          38         zipNumZones       word          number of names
  15543.       returned
  15544.       ¨          40         zipLastFlag              byte            nonzero if
  15545.       no more names
  15546.       Æ          42         zipInfoField             70 bytes     for use by
  15547.       ZIP; first word set to 0
  15548.  
  15549.  
  15550. Parameter Block for dspInit and dspCLInit
  15551.  
  15552.      ¨       16      ioResult             word         result code 
  15553.      Æ       24      ioCRefNum      word         driver reference number
  15554.      Æ       26      csCode                word         dspInit or dspCLInit
  15555.      ¨       32      ccbRefNum       word         reference number of CCB
  15556.      Æ       34      ccbPtr                   long          pointer to CCB
  15557.      Æ       38      userRoutine      long          pointer to routine to call
  15558.      on 
  15559.  
  15560.                                                                          events
  15561.      Æ       42      sendQSize          word         size in bytes of the send
  15562.      queue
  15563.      Æ       44      sendQueue         long          pointer to send queue
  15564.      Æ       48      recvQSize           word         size in bytes of the
  15565.      receive queue
  15566.      Æ       50      recvQueue          long          pointer to receive queue
  15567.      Æ       54      attnPtr                  long          pointer to buffer
  15568.      for incoming 
  15569.  
  15570.  
  15571.  
  15572.      ´       58      localSocket          byte           DDP socket number for
  15573.      this 
  15574.  
  15575.                                                                           end
  15576.  
  15577.  
  15578. Parameter Block for dspOptions
  15579.  
  15580.       ¨       16       ioResult             word          result code 
  15581.       Æ       24       ioCRefNum      word         driver reference number
  15582.       Æ       26       csCode                 word         always dspOptions
  15583.       Æ       32       ccbRefNum        word         reference number of CCB
  15584.       Æ       34       sendBlocking     word         send-blocking threshold
  15585.       Æ       38       badSeqMax          byte           threshold to send
  15586.       retransmit advice
  15587.       Æ       39       useCheckSum    byte           use DDP checksum?
  15588.  
  15589.  
  15590. Parameter Block for dspOpen, dspCLListen, and dspCLDeny
  15591.  
  15592.       ¨       16        ioResult              word         result code 
  15593.       Æ       24        ioCRefNum       word         driver reference number
  15594.       Æ       26         csCode                word         dspOpen,
  15595.       dspCLListen, or 
  15596.  
  15597.  
  15598.       Æ       32        ccbRefNum        word         reference number of CCB
  15599.       ¨       34        localCID              word         ID of this connection
  15600.       end
  15601.       ´       36        remoteCID          word        ID of remote connection
  15602.       end
  15603.       ´       38        remoteAddress   long         remote internet address
  15604.       Æ       42        filterAddress       long         filter for open
  15605.       connection requests
  15606.       ´       46        sendSeq                long         initial send
  15607.       sequence number
  15608.       ´       50        sendWindow     word        initial size of remote
  15609.       receive queue
  15610.       Æ       52        recvSeq                 long         initial receive
  15611.       sequence number
  15612.       ´       56        attnSendSeq         long        attention send sequence
  15613.       number
  15614.       Æ       60        attnRecvSeq         long        attention receive
  15615.       sequence number
  15616.       Æ       64        ocMode                 byte          connection-opening
  15617.       mode
  15618.       Æ       65        ocInterval             byte         interval between
  15619.       open requests
  15620.       Æ       66        ocMaximum        byte         retries of open-connection
  15621.       request
  15622.  
  15623.  
  15624. Parameter Block for dspNewCID
  15625.  
  15626.       ¨       16        ioResult              word           result code 
  15627.       Æ       24        ioCRefNum       word           driver reference number
  15628.       Æ       26        csCode                 word            always dspNewCID
  15629.       Æ       32        ccbRefNum        word           reference number of CCB
  15630.       ¨       34        newCID               word           ID of new connection
  15631.  
  15632.  
  15633. Parameter Block for dspClose, dspRemove, and dspCLRemove, and dspCLRemove
  15634.  
  15635.       ¨       16        ioResult               word        result code 
  15636.       Æ       24        ioCRefNum        word        driver reference number
  15637.       Æ       26        csCode                  word        dspClose, dspRemove,
  15638.       or 
  15639.  
  15640.  
  15641.       Æ       32        ccbRefNum         word        reference number of CCB
  15642.       Æ       34        abort                      byte          abort send
  15643.       requests or connection 
  15644.  
  15645.                                                                             if
  15646.                                                                             not
  15647.                                                                             0
  15648.  
  15649.  
  15650. Parameter Block for dspStatus
  15651.  
  15652.       ¨       16        ioResult               word              result code 
  15653.       Æ       24        ioCRefNum        word              driver reference
  15654.       number
  15655.       Æ       26        csCode                  word              always
  15656.       dspStatus
  15657.       Æ       32        ccbRefNum        word               reference number of
  15658.       CCB
  15659.       ¨       34        statusCCB            pointer          pointer to CCB
  15660.       ¨       38        sendQPending   word               bytes waiting to be
  15661.       sent or 
  15662.                                                                                
  15663.  
  15664.       ¨       40        sendQFree           word             available send
  15665.       queue in bytes
  15666.       ¨       42        recvQPending    word              bytes waiting to be
  15667.       read from queue
  15668.       ¨       44        recvQFree            word             available receive
  15669.       queue in bytes 
  15670.  
  15671.  
  15672. Parameter Block for dspRead and dspWrite
  15673.  
  15674.       ¨       16        ioResult            word           result code 
  15675.       Æ       24        ioCRefNum     word           driver reference number
  15676.       Æ       26        csCode               word           dspRead or dspWrite
  15677.       Æ       32        ccbRefNum      word           reference number of CCB
  15678.       Æ       34        reqCount          word           requested number of
  15679.       bytes
  15680.       ¨       36        actCount           word           actual number of bytes
  15681.       read or 
  15682.  
  15683.  
  15684.       Æ       38        dataPtr             pointer        pointer to data
  15685.       buffer
  15686.       ¨       42        eom                  byte              1 if
  15687.       end-of-message; 0 otherwise
  15688.       Æ       43        flush                 byte              1 to send data
  15689.       now; 0 otherwise
  15690.  
  15691.  
  15692. Parameter Block for dspAttention and dspReset
  15693.  
  15694.       ¨       16        ioResult              word            result code 
  15695.       Æ       24        ioCRefNum      word            driver reference number
  15696.       Æ       26        csCode                word            dspAttention or
  15697.       dspReset
  15698.       Æ       32        ccbRefNum       word            reference number of CCB
  15699.       Æ       34        attnCode            word            client attention
  15700.       code
  15701.       Æ       36        attnSize              word            size of attention
  15702.       data in bytes
  15703.       Æ       38        attnData              pointer        pointer to
  15704.       attention data
  15705.  
  15706.  
  15707. .ENET Driver Parameter Block
  15708.  
  15709.     16         ¨        ioResult              word            result code 
  15710.     26         Æ        csCode                 word            routine selector
  15711.     28         Æ        eMultiAddr        6 bytes         multicast address
  15712.     28         Æ        eProtType           word            Ethernet protocol
  15713.     type
  15714.     30         Æ        ePointer              long             pointer 
  15715.     34         Æ        eBuffSize            word            size of buffer
  15716.     36         ¨        eDataSize            word           number of bytes read
  15717. _______________________________________________________________________________
  15718.  
  15719.  
  15720. æKY About…The…AppleTalkManager…Chapter
  15721. æC »ABOUT THIS CHAPTER                                       AppleTalkManager
  15722. _______________________________________________________________________________
  15723.  
  15724. The AppleTalk Manager is an interface to a pair of RAM device drivers that allow
  15725. Macintosh programs to send and receive information via an AppleTalk network. This
  15726. chapter describes the AppleTalk Manager in detail.
  15727.  
  15728. The AppleTalk Manager has been enhanced through the implementation of new protocols
  15729. and an increase in the functionality of the existing interface.
  15730.  
  15731. Reader’s guide:  The AppleTalk Manager provides services that allow Macintosh
  15732.                  programs to interact with clients in devices connected to an
  15733.                  AppleTalk network.  Hence you need the information in this
  15734.                  chapter only if your application uses AppleTalk.
  15735.  
  15736. The following is a brief summary of the changes that have been made to the AppleTalk
  15737. Manager interface.
  15738.  
  15739.   •  New parameter block–style Pascal calls have been added for the entire
  15740.      AppleTalk Manager.  These new calls give the application programmer
  15741.      better control of AppleTalk operation within an application.
  15742.   •  At open time, the .MPP driver can be told to pick a node number in
  15743.      the server range.  This is a more time consuming but more thorough
  15744.      operation than is selecting a node number in the workstation range,
  15745.      and it is required for devices acting as servers.
  15746.   •  Multiple concurrent NBP requests are now supported (just as multiple
  15747.      concurrent ATP requests have been supported).  The KillNBP command
  15748.      has been implemented to abort an outstanding NBP request.
  15749.   •  ATP requests can now be sent through client-specified sockets, instead
  15750.      of having ATP pick the socket itself.
  15751.   •  The ability to send packets to one’s own node is supported (although
  15752.      this functionality is, in the default case, disabled).
  15753.   •  Two new ATP abort calls have been added: KillSendReq and KillGetReq.
  15754.      KillSendReq is functionally equivalent to RelTCB, although its
  15755.      arguments are different.  KillGetReq is a new call for aborting
  15756.      outstanding GetRequests.
  15757.   •  Additional machine-dependent resources have been added to support,
  15758.      for example, more dynamic sockets and more concurrent ATP requests. 
  15759.   •  A new protocol called the Echo Protocol (EP) is supported.
  15760.   •  A new driver, .XPP, has been added.  The .XPP driver implements the
  15761.      workstation side of the AppleTalk Session Protocol (ASP) and a small
  15762.      portion of the AppleTalk Filing Protocol.
  15763.  
  15764. To determine if your application is running on a machine that supports these enhanced
  15765. features, check the version number of the .MPP driver (at offset DCtlQueue+1 in the
  15766. Device Control Entry).  A version number of 48 (NCVersion) or greater indicates the
  15767. presence of the new drivers.
  15768.  
  15769. You should already be familiar with:
  15770.  
  15771.   •  events, as discussed in the Toolbox Event Manager chapter
  15772.   •  interrupts and the use of devices and device drivers, as described in
  15773.      the Device Manager chapter, if you want to write your own assembly-
  15774.      language additions to the AppleTalk Manager
  15775.   •  the Inside AppleTalk manual, if you want to understand AppleTalk
  15776.      protocols in detail
  15777.  
  15778. _______________________________________________________________________________
  15779.  
  15780.  
  15781. æKY AppleTalk…Protocols
  15782. æC »APPLETALK PROTOCOLS                                      AppleTalkManager
  15783. _______________________________________________________________________________
  15784.  
  15785. The AppleTalk Manager provides a variety of services that allow Macintosh programs to
  15786. interact with programs in devices connected to an AppleTalk network. This interaction,
  15787. achieved through the exchange of variable-length blocks of data (known as packets)
  15788. over AppleTalk, follows well-defined sets of rules known as protocols.
  15789.  
  15790. Although most programmers using AppleTalk needn’t understand the details of these
  15791. protocols, they should understand the information in this section—what the services
  15792. provided by the different protocols are, and how the protocols are interrelated.
  15793. Detailed information about AppleTalk protocols is available in Inside AppleTalk.
  15794.  
  15795. The AppleTalk system architecture consists of a number of protocols arranged in
  15796. layers. Each protocol in a specific layer provides services to higher-level layers
  15797. (known as the protocol’s clients) by building on the services provided by lower-level
  15798. layers. A Macintosh program can use services provided by any of the layers in order
  15799. to construct more sophisticated or more specialized services.  Figure 1 shows the
  15800. AppleTalk Protocols and their corresponding network layers.
  15801.  
  15802. The AppleTalk Manager contains the following protocols:
  15803.  
  15804.   •  AppleTalk Link Access Protocol
  15805.   •  Datagram Delivery Protocol
  15806.   •  Routing Table Maintenance Protocol
  15807.   •  Name-Binding Protocol
  15808.   •  AppleTalk Transaction Protocol
  15809.  
  15810. The following protocols have been added to the AppleTalk Manager:
  15811.  
  15812.   •  Echo Protocol
  15813.   •  AppleTalk Session Protocol (workstation side)
  15814.   •  AppleTalk Filing Protocol (small portion of the workstation side)
  15815.  
  15816. In Figure 1, the lines indicate the interaction between the protocols.  Notice that
  15817. like the Routing Table Maintenance Protocol, the Echo Protocol is not directly accessible
  15818. to Macintosh programs.
  15819.  
  15820. The details of these protocols are provided in Inside AppleTalk.
  15821.  
  15822. •••Refer to Figure 1.•••
  15823.  
  15824. Figure 1–AppleTalk Protocols and OSI Network Layers
  15825.  
  15826. Figure 2 illustrates the Macintosh AppleTalk Drivers and the layered structure of the
  15827. protocols which are accessible through each driver.  Note that the Routing Table
  15828. Maintenance Protocol isn’t directly accessible to Macintosh Programs.
  15829.  
  15830. •••Refer to Figure 2.•••
  15831.  
  15832. Figure 2–Macintosh AppleTalk Drivers
  15833.  
  15834. The AppleTalk Link Access Protocol (ALAP) provides the lowest-level services of the
  15835. AppleTalk system. Its main function is to control access to the AppleTalk network
  15836. among various competing devices. Each device connected to an AppleTalk network, known
  15837. as a node, is assigned an eight-bit node ID number that identifies the node. ALAP
  15838. ensures that each node on an AppleTalk network has a unique node ID, assigned dynamically
  15839. when the node is started up.
  15840.  
  15841. ALAP provides its clients with node-to-node delivery of data frames on a single
  15842. AppleTalk network. An ALAP frame is a variable-length packet of data preceded and
  15843. followed by control information referred to as the ALAP frame header and frame trailer,
  15844. respectively. The ALAP frame header includes the node IDs of the frame’s destination
  15845. and source nodes. The AppleTalk hardware uses the destination node ID to deliver the
  15846. frame. The frame’s source node ID allows a program in the receiving node to determine
  15847. the identity of the source. A sending node can ask ALAP to send a frame to all nodes
  15848. on the AppleTalk network; this broadcast service is obtained by specifying a destination
  15849. node ID of 255.
  15850.  
  15851. ALAP can have multiple clients in a single node. When a frame arrives at a node, ALAP
  15852. determines which client it should be delivered to by reading the frame’s ALAP protocol
  15853. type. The ALAP protocol type is an eight-bit quantity, contained in the frame’s
  15854. header, that identifies the ALAP client to whom the frame will be sent. ALAP calls
  15855. the client’s protocol handler, which is a software process in the node that reads in
  15856. and then services the frames. The protocol handlers for a node are listed in a protocol
  15857. handler table.
  15858.  
  15859. An ALAP frame trailer contains a 16-bit frame check sequence generated by the AppleTalk
  15860. hardware. The receiving node uses the frame check sequence to detect transmission
  15861. errors, and discards frames with errors. In effect, a frame with an error is “lost”
  15862. in the AppleTalk network, because ALAP doesn’t attempt to recover from errors by
  15863. requesting the sending node to retransmit such frames. Thus ALAP is said to make a
  15864. “best effort” to deliver frames, without any guarantee of delivery.
  15865.  
  15866. An ALAP frame can contain up to 600 bytes of client data. The first two bytes must be
  15867. an integer equal to the length of the client data (including the length bytes themselves).
  15868.  
  15869. Datagram Delivery Protocol (DDP) provides the next-higher level protocol in the
  15870. AppleTalk architecture, managing socket-to-socket delivery of datagrams over AppleTalk
  15871. internets. DDP is an ALAP client, and uses the node-to-node delivery service provided
  15872. by ALAP to send and receive datagrams. Datagrams are packets of data transmitted by
  15873. DDP. A DDP datagram can contain up to 586 bytes of client data. Sockets are logical
  15874. entities within the nodes of a network; each socket within a given node has a unique
  15875. eight-bit socket number.
  15876.  
  15877. On a single AppleTalk network, a socket is uniquely identified by its AppleTalk
  15878. address—its socket number together with its node ID. To identify a socket in the
  15879. scope of an AppleTalk internet, the socket’s AppleTalk address and network number are
  15880. needed. Internets are formed by interconnecting AppleTalk networks via intelligent
  15881. nodes called bridges. A network number is a 16-bit number that uniquely identifies a
  15882. network in an internet. A socket’s AppleTalk address together with its network number
  15883. provide an internet-wide unique socket identifier called an internet address.
  15884.  
  15885. Sockets are owned by socket clients, which typically are software processes in the
  15886. node. Socket clients include code called the socket listener, which receives and
  15887. services datagrams addressed to that socket. Socket clients must open a socket before
  15888. datagrams can be sent or received through it. Each node contains a socket table that
  15889. lists the listener for each open socket.
  15890.  
  15891. A datagram is sent from its source socket through a series of AppleTalk networks,
  15892. being passed on from bridge to bridge, until it reaches its destination network. The
  15893. ALAP in the destination network then delivers the datagram to the node containing the
  15894. destination socket. Within that node the datagram is received by ALAP calling the DDP
  15895. protocol handler, and by the DDP protocol handler in turn calling the destination
  15896. socket listener, which for most applications will be a higher-level protocol such as
  15897. the AppleTalk Transaction Protocol.
  15898.  
  15899. Bridges on AppleTalk internets use the Routing Table Maintenance Protocol (RTMP) to
  15900. maintain routing tables for routing datagrams through the internet. In addition,
  15901. nonbridge nodes use RTMP to determine the number of the network to which they’re
  15902. connected and the node ID of one bridge on their network. The RTMP code in nonbridge
  15903. nodes contains only a subset of RTMP (the RTMP stub), and is a DDP client owning
  15904. socket number 1 (the RTMP socket).
  15905.  
  15906. Socket clients are also known as network-visible entities, because they’re the primary
  15907. accessible entities on an internet. Network-visible entities can choose to identify
  15908. themselves by an entity name, an identifier of the form
  15909.  
  15910.   object:type@zone
  15911.  
  15912. Each of the three fields of this name is an alphanumeric string of up to 32 characters.
  15913. The object and type fields are arbitrary identifiers assigned by a socket client, to
  15914. provide itself with a name and type descriptor (for example, abs:Mailbox). The zone
  15915. field identifies the zone in which the socket client is located; a zone is an arbitrary
  15916. subset of AppleTalk networks in an internet. A socket client can identify itself by
  15917. as many different names as it chooses. These aliases are all treated as independent
  15918. identifiers for the same socket client.
  15919.  
  15920. The Name-Binding Protocol (NBP) maintains a names table in each node that contains
  15921. the name and internet address of each entity in that node. These name-address pairs
  15922. are called NBP tuples. The collection of names tables in an internet is known as the
  15923. names directory.
  15924.  
  15925. NBP allows its clients to add or delete their name-address tuples from the
  15926. node’s names table. It also allows its clients to obtain the internet addresses of
  15927. entities from their names. This latter operation, known as name lookup (in the names
  15928. directory), requires that NBP install itself as a DDP client and broadcast special
  15929. name-lookup packets to the nodes in a specified zone. These datagrams are sent by NBP
  15930. to the names information socket—socket number 2 in every node using NBP.
  15931.  
  15932. NBP clients can use special meta-characters in place of one or more of the three
  15933. fields of the name of an entity it wishes to look up. The character “=” in the object
  15934. or type field signifies “all possible values”. The zone field can be replaced by “*”,
  15935. which signifies “this zone”—the zone in which the NBP client’s node is located. For
  15936. example, an NBP client performing a lookup with the name
  15937.  
  15938.   =:Mailbox@*
  15939.  
  15940. will obtain in return the entity names and internet addresses of all mailboxes in the
  15941. client’s zone (excluding the client’s own names and addresses). The client can specify
  15942. whether one or all of the matching names should be returned.
  15943.  
  15944. NBP clients specify how thorough a name lookup should be by providing NBP with the
  15945. number of times (retry count) that NBP should broadcast the lookup packets and the
  15946. time interval (retry interval) between these retries.
  15947.  
  15948. As noted above, ALAP and DDP provide “best effort” delivery services with no recovery
  15949. mechanism when packets are lost or discarded because of errors. Although for many
  15950. situations such a service suffices, the AppleTalk Transaction Protocol (ATP) provides
  15951. a reliable loss-free transport service. ATP uses transactions, consisting of a transaction
  15952. request and a transaction response, to deliver data reliably. Each transaction is
  15953. assigned a 16-bit transaction ID number to distinguish it from other transactions. A
  15954. transaction request is retransmitted by ATP until a complete response has been received,
  15955. thus allowing for recovery from packet-loss situations. The retry interval and retry
  15956. count are specified by the ATP client sending the request.
  15957.  
  15958. Although transaction requests must be contained in a single datagram, transaction
  15959. responses can consist of as many as eight datagrams. Each datagram in a response is
  15960. assigned a sequence number from 0 to 7, to indicate its ordering within the response.
  15961.  
  15962. ATP is a DDP client, and uses the services provided by DDP to transmit requests and
  15963. responses. ATP supports both at-least-once and exactly-once transactions. Four of the
  15964. bytes in an ATP header, called the user bytes, are provided for use by ATP’s clients—they’re
  15965. ignored by ATP.
  15966.  
  15967. ATP’s transaction model and means of recovering from datagram loss are covered in
  15968. detail below.
  15969.  
  15970. The Echo Protocol (EP) provides an echoing service through static socket number 4
  15971. known as the echoer socket.  The echoer listens for packets received through this
  15972. socket.  Any correctly formed packet sent to the echoer socket on a node will be
  15973. echoed back to its sender.
  15974.  
  15975. This simple protocol can be used for two important purposes:
  15976.  
  15977.   •  EP can be used by any Datagram Delivery Protocol (DDP) client to
  15978.      determine if a particular node (known to have an echoer) is accessible
  15979.      over an internet.
  15980.   •  EP is useful in determining the average time it takes for a packet to
  15981.      travel to a remote node and back.  This is very helpful in developing
  15982.      client-dependent heuristics for estimating the timeouts to be specified
  15983.      by clients of ATP, ASP, and other protocols.
  15984.  
  15985. Programs cannot access EP directly via the AppleTalk Manager.  The EP implementation
  15986. exists solely to respond to EP requests sent by other nodes.  EP is a DDP client
  15987. residing on statically-assigned socket 4, the echoing socket.  Clients wishing to
  15988. send EP requests (and receive EP responses) should use the Datagram Delivery Protocol
  15989. (DDP) to send the appropriate packet.  For more information about the EP packet
  15990. format, see Inside AppleTalk.
  15991.  
  15992. The AppleTalk Session Protocol (ASP) provides for the setting up, maintaining and
  15993. closing down of a session.  A session is a logical relationship between two network
  15994. entities, a workstation and a server.  The workstation tells the server what to do,
  15995. and the server responds with the appropriate actions.  ASP makes sure that the session
  15996. dialog is maintained in the correct sequence and that both ends of the conversation
  15997. are properly participating.
  15998.  
  15999. ASP will generally be used between two communicating network entities where one is
  16000. providing a service to the other (for example, a server is providing a service to a
  16001. workstation) and the service provided is state-dependent.  That is, the response to a
  16002. particular request from an entity is dependent upon other previous requests from that
  16003. entity.  For example, a request to read bytes from a file is dependent upon a previous
  16004. request to open that file in the first place.  However, a request to return the time
  16005. of day is independent of all such previous requests.
  16006.  
  16007. When the service provided is state-dependent, requests must be delivered to the
  16008. server in the same order as generated by the workstation.  ASP guarantees requests
  16009. are delivered to the server in the order in which they are issued, and that duplicate
  16010. requests are never delivered (another requirement of state-dependent service).
  16011.  
  16012. ASP is an asymmetric protocol, providing one set of services to the workstation and a
  16013. different set of services to the server.
  16014.  
  16015. ASP workstation clients initiate (open) sessions, send requests (commands) on that
  16016. session, and close sessions down.  ASP server clients receive and respond
  16017. (through command replies) to these requests.  ASP guarantees that these requests are
  16018. delivered in the same order as they are made, and without duplication.  ASP is also
  16019. responsible for closing down the session if one end fails or becomes unreachable, and
  16020. will inform its client (either server or workstation) of the action.
  16021.  
  16022. ASP also provides various additional services, such as allowing a workstation to
  16023. obtain server status information without opening a session to a server, writing
  16024. blocks of data from the workstation to the server end of the session, and providing
  16025. the ability for a server to send an attention message to the workstation.
  16026.  
  16027. ASP assumes that the workstation client has a mechanism for looking up the network
  16028. address of the server with which it wants to set up a session.
  16029. (Generally this is done using the AppleTalk Name Binding Protocol.)
  16030.  
  16031. Both ends of the session periodically check to see that the other end of the session
  16032. is still responsive.  If one end fails or becomes unreachable the other end closes
  16033. the session.
  16034.  
  16035. ASP is a client of ATP and calls ATP for transport services.
  16036.  
  16037. ASP does not
  16038.  
  16039.   •  ensure that consecutive commands complete in the order in which they
  16040.      were sent (and delivered) to the server
  16041.   •  understand or interpret the syntax or the semantics of the commands
  16042.      sent to the server by the workstation
  16043.   •  allow the server to send commands to the workstation  (The server
  16044.      is allowed to alert the workstation through the server’s attention
  16045.      mechanism only.)
  16046.  
  16047. Note:  The .XPP driver does implement the workstation side of the
  16048.        AppleTalk Filing Protocol login command.
  16049.  
  16050. The AppleTalk Filing Protocol (AFP) allows a workstation on an AppleTalk network to
  16051. access files on an AFP file server.  AFP specifies a remote filing system that provides
  16052. user authentication and an access control mechanism that supports volume and folder-level
  16053. access rights.  For details of AFP, refer to Inside AppleTalk.
  16054.  
  16055. _______________________________________________________________________________
  16056.  
  16057.  
  16058. æKY AppleTalk…Transaction…Protocol
  16059. æC »APPLETALK TRANSACTION PROTOCOL                           AppleTalkManager
  16060. _______________________________________________________________________________
  16061.  
  16062. This section covers ATP in greater depth, providing more detail about three of its
  16063. fundamental concepts:  transactions, buffer allocation, and recovery of lost datagrams.
  16064.  
  16065. _______________________________________________________________________________
  16066.  
  16067. »Transactions
  16068.  
  16069. A transaction is a interaction between two ATP clients, known as the requester and
  16070. the responder. The requester calls the .ATP driver in its node to send a transaction
  16071. request (TReq) to the responder, and then awaits a response. The TReq is received by
  16072. the .ATP driver in the responder’s node and is delivered to the responder. The responder
  16073. then calls its .ATP driver to send back a transaction response (TResp), which is
  16074. received by the requester’s .ATP driver and delivered to the requester. Figure 3
  16075. illustrates this process.
  16076.  
  16077. •••Refer to Figure 3.•••
  16078.  
  16079. Figure 3–Transaction Process
  16080.  
  16081. Simple examples of transactions are:
  16082.  
  16083.   •  read a counter, reset it and send back the value read
  16084.   •  read six sectors of a disk and send back the data read
  16085.   •  write the data sent in the TReq to a printer
  16086.  
  16087. A basic assumption of the transaction model is that the amount of ATP data sent in
  16088. the TReq specifying the operation to be performed is small enough to fit in a single
  16089. datagram. A TResp, on the other hand, may span several datagrams, as in the second
  16090. example. Thus, a TReq is a single datagram, while a TResp consists of up to eight
  16091. datagrams, each of which is assigned a sequence number from 0 to 7 to indicate its
  16092. position in the response.
  16093.  
  16094. The requester must, before calling for a TReq to be sent, set aside enough buffer
  16095. space to receive the datagram(s) of the TResp. The number of buffers allocated (in
  16096. other words, the maximum number of datagrams that the responder can send) is indicated
  16097. in the TReq by an eight-bit bit map. The bits of this bit map are numbered 0 to 7
  16098. (the least significant bit being number 0); each bit corresponds to the response
  16099. datagram with the respective sequence number.
  16100.  
  16101. _______________________________________________________________________________
  16102.  
  16103. »Datagram Loss Recovery
  16104.  
  16105. The way that ATP recovers from datagram loss situations is best explained by an
  16106. example; see Figure 4. Assume that the requester wants to read six sectors of 512
  16107. bytes each from the responder’s disk. The requester puts aside six 512-byte buffers
  16108. (which may or may not be contiguous) for the response datagrams, and calls ATP to
  16109. send a TReq. In this TReq the bit map is set to binary 00111111 or decimal 63. The
  16110. TReq carries a 16-bit transaction ID, generated by the requester’s .ATP driver before
  16111. sending it. (This example assumes that the requester and responder have already
  16112. agreed that each buffer can hold 512
  16113. bytes.) The TReq is delivered to the responder, which reads the six disk sectors and
  16114. sends them back, through ATP, in TResp datagrams bearing sequence numbers 0 through
  16115. 5. Each TResp datagram also carries exactly the same transaction ID as the TReq to
  16116. which they’re responding.
  16117.  
  16118. There are several ways that datagrams may be lost in this case. The original TReq
  16119. could be lost for one of many reasons. The responding node might be too busy to
  16120. receive the TReq or might be out of buffers for receiving it, there could be an
  16121. undetected collision on the network, a bit error in the transmission line, and so on.
  16122. To recover from such errors, the requester’s .ATP driver maintains an ATP retry timer
  16123. for each transaction sent. If this timer expires and the complete TResp has not been
  16124. received, the TReq is retransmitted and the retry timer is restarted.
  16125.  
  16126. A second error situation occurs when one or more of the TResp datagrams isn’t received
  16127. correctly by the requester’s .ATP driver (datagram 1 in Figure 4). Again, the retry
  16128. timer will expire and the complete TResp will not have been received; this will
  16129. result in a retransmission of the TReq. However, to avoid unnecessary retransmission
  16130. of the TResp datagrams already properly received, the bit map of this retransmitted
  16131. TReq is modified to reflect only those datagrams not yet received. Upon receiving
  16132. this TReq, the responder retransmits only the missing response datagrams.
  16133.  
  16134. Another possible failure is that the responder’s .ATP driver goes down or the responder
  16135. becomes unreachable through the underlying network system. In this case, retransmission
  16136. of the TReq could continue indefinitely. To avoid this situation, the requester
  16137. provides a maximum retry count; if this count is exceeded, the requester’s .ATP
  16138. driver returns an appropriate error message to the requester.
  16139.  
  16140. •••Refer to Figure 4.•••
  16141.  
  16142. Figure 4–Datagram Loss Recovery
  16143.  
  16144. Note:  There may be situations where, due to an anticipated delay, you’ll
  16145.        want a request to be retransmitted more than 255 times; specifying a
  16146.        retry count of 255 indicates “infinite retries” to ATP and will cause
  16147.        a message to be retransmitted until the request has either been
  16148.        serviced, or been cancelled through a specific call.
  16149. _______________________________________________________________________________
  16150.  
  16151. »THE APPLETALK MANAGER                                            
  16152. _______________________________________________________________________________
  16153.  
  16154. Finally, in our example, what if the responder is able to provide only four disk
  16155. sectors (having reached the end of the disk) instead of the six requested? To handle
  16156. this situation, there’s an end-of-message (EOM) flag in each TResp datagram. In this
  16157. case, the TResp datagram numbered 3 would come with this flag set. The reception of
  16158. this datagram informs the requester’s .ATP driver that TResps numbered 4 and 5 will
  16159. not be sent and should not be expected.
  16160.  
  16161. When the transaction completes successfully (all expected TResp datagrams are received
  16162. or TResp datagrams numbered 0 to n are received with datagram n’s EOM flag set), the
  16163. requester is informed and can then use the data received in the TResp.
  16164.  
  16165. ATP provides two classes of service:  at-least-once (ALO) and exactly-once (XO). The
  16166. TReq datagram contains an XO flag that’s set if XO service is required and cleared if
  16167. ALO service is adequate. The main difference between the two is in the sequence of
  16168. events that occurs when the TReq is received by the responder’s .ATP driver.
  16169.  
  16170. In the case of ALO service, each time a TReq is received (with the XO flag cleared),
  16171. it’s delivered to the responder by its .ATP driver; this is true even for retransmitted
  16172. TReqs of the same transaction. Each time the TReq is delivered, the responder performs
  16173. the requested operation and sends the necessary TResp datagrams. Thus, the requested
  16174. operation is performed at least once, and perhaps several times, until the transaction
  16175. is completed at the requester’s end.
  16176.  
  16177. The at-least-once service is satisfactory in a variety of situations—for instance, if
  16178. the requester wishes to read a clock or a counter being maintained at the responder’s
  16179. end. However, in other circumstances, repeated execution of the requested operation
  16180. is unacceptable. This is the case, for instance, if the requester is sending data to
  16181. be printed at the responding end; exactly-once service is designed for such situations.
  16182.  
  16183. The responder’s .ATP driver maintains a transactions list of recently received XO
  16184. TReqs. Whenever a TReq is received with its XO flag set, the driver goes through this
  16185. list to see if this is a retransmitted TReq. If it’s the first TReq of a transaction,
  16186. it’s entered into the list and delivered to the responder. The responder executes the
  16187. requested operation and calls its driver to send a TResp. Before sending it out, the
  16188. .ATP driver saves the TResp in the list.
  16189.  
  16190. When a retransmitted TReq for the same XO transaction is received, the responder’s
  16191. .ATP driver will find a corresponding entry in the list. The retransmitted TReq is
  16192. not delivered to the responder; instead, the driver automatically retransmits the
  16193. response datagrams that were saved in the list. In this way, the responder never sees
  16194. the retransmitted TReqs and the requested operation is performed only once.
  16195.  
  16196. ATP must include a mechanism for eventually removing XO entries from the responding
  16197. end’s transaction list; two provisions are made for this. When the requester’s .ATP
  16198. driver has received all the TResp datagrams of a particular transaction, it sends a
  16199. datagram known as a transaction release (TRel); this tells the responder’s .ATP
  16200. driver to remove the transaction from the list. However, the TRel could be lost in
  16201. the network (or the responding end may die, and so on), leaving the entry in the list
  16202. forever. To account for this situation, the responder’s .ATP driver maintains a
  16203. release timer for each transaction. If this timer expires and no activity has occurred
  16204. for the transaction, its entry is removed from the transactions list.
  16205.  
  16206. _______________________________________________________________________________
  16207.  
  16208.  
  16209. æKY About…the…AppleTalk…Manager
  16210. æC »ABOUT THE APPLETALK MANAGER                              AppleTalkManager
  16211. _______________________________________________________________________________
  16212.  
  16213. The AppleTalk Manager is divided into three parts (see Figure 5):
  16214.  
  16215.   •  A lower-level driver called “.MPP” that contains code to implement ALAP,
  16216.      DDP, NBP, and the RTMP stub; this includes separate code resources loaded
  16217.      in when an NBP name is registered or looked up.
  16218.   •  A higher-level driver called “.ATP” that implements ATP.
  16219.   •  A Pascal interface to these two drivers, which is a set of Pascal data
  16220.      types and routines to aid Pascal programmers in calling the AppleTalk
  16221.      Manager.
  16222.  
  16223. •••Refer to Figure 5.•••
  16224.  
  16225. Figure 5–Calling the AppleTalk Manager
  16226.  
  16227. The two drivers and the interface to them are not in ROM; your application must link
  16228. to the appropriate object files.
  16229.  
  16230. Pascal programmers make calls to the AppleTalk Manager’s Pascal interface, which in
  16231. turn makes Device Manager Control calls to the two drivers. Assembly-language programmers
  16232. make Device Manager Control calls directly to the drivers.
  16233.  
  16234. Note:  Pascal programmers can, of course, make PBControl calls directly
  16235.        if they wish.
  16236.  
  16237. The AppleTalk Manager provides ALAP routines that allow a program to:
  16238.  
  16239.   •  send a frame to another node
  16240.   •  receive a frame from another node
  16241.   •  add a protocol handler to the protocol handler table
  16242.   •  remove a protocol handler from the protocol handler table
  16243.  
  16244. Each node may have up to four protocol handlers in its protocol handler table, two of
  16245. which are currently used by DDP.
  16246.  
  16247. By calling DDP, socket clients can:
  16248.  
  16249.   •  send a datagram via a socket
  16250.   •  receive a datagram via a socket
  16251.   •  open a socket and add a socket listener to the socket table
  16252.   •  close a socket and remove a socket listener from the socket table
  16253.  
  16254. Each node may have up to 12 open sockets in its socket table.
  16255.  
  16256. Programs cannot access RTMP directly via the AppleTalk Manager; RTMP exists solely
  16257. for the purpose of providing DDP with routing information.
  16258.  
  16259. The NBP code allows a socket client to:
  16260.  
  16261.   •  register the name and socket number of an entity in the node’s names table
  16262.   •  determine the address (and confirm the existence) of an entity
  16263.   •  delete the name of an entity from the node’s names table
  16264.  
  16265. The AppleTalk Manager’s .ATP driver allows a socket client to do the following:
  16266.  
  16267.   •  open a responding socket to receive requests
  16268.   •  send a request to another socket and get back a response
  16269.   •  receive a request via a responding socket
  16270.   •  send a response via a responding socket
  16271.   •  close a responding socket
  16272.  
  16273. Note:  Although the AppleTalk Manager provides four different protocols
  16274.        for your use, you’re not bound to use all of them. In fact, most
  16275.        programmers will use only the NBP and ATP protocols.
  16276.  
  16277. AppleTalk communicates via channel B of the Serial Communications Controller
  16278. (SCC). When the Macintosh is started up with a disk containing the AppleTalk code,
  16279. the status of serial port B is checked. If port B isn’t being used by another device
  16280. driver, and is available for use by AppleTalk, the .MPP driver is loaded into the
  16281. system heap. On a Macintosh 128K, only the MPP code is loaded at system startup; the
  16282. .ATP driver and NBP code are read into the application heap when the appropriate
  16283. commands are issued. On a Macintosh 512K or XL, all AppleTalk code is loaded into the
  16284. system heap at system startup.
  16285.  
  16286. After loading the AppleTalk code, the .MPP driver installs its own interrupt handlers,
  16287. installs a task into the vertical retrace queue, and prepares the SCC for use. It
  16288. then chooses a node ID for the Macintosh and confirms that the node ID isn’t already
  16289. being used by another node on the network.
  16290.  
  16291. Warning:  For this reason it’s imperative that the Macintosh be connected
  16292.           to the AppleTalk network through serial port B (the printer port)
  16293.           before being switched on.
  16294.  
  16295. The AppleTalk Manager also provides Pascal routines for opening and closing the .MPP
  16296. and .ATP drivers. The open calls allow a program to load AppleTalk code at times
  16297. other than system startup. The close calls allow a program to remove the AppleTalk
  16298. code from the Macintosh; the use of close calls is highly discouraged, since other
  16299. co-resident programs are then “disconnected” from AppleTalk. Both sets of calls are
  16300. described in detail under “Calling the AppleTalk Manager from Pascal”.
  16301.  
  16302. Warning:  If, at system startup, serial port B isn’t available for use by
  16303.           AppleTalk, the .MPP driver won’t open. However, a driver doesn’t
  16304.           return an error message when it fails to open. Pascal programmers
  16305.           must ensure the proper opening of AppleTalk by calling one of the
  16306.           two routines for opening the AppleTalk drivers (either MPPOpen or
  16307.           ATPLoad). If AppleTalk was successfully loaded at system startup,
  16308.           these calls will have no effect; otherwise they’ll check the
  16309.           availability of port B, attempt to load the AppleTalk code, and
  16310.           return an appropriate result code.
  16311.  
  16312. Assembly-language note:  Assembly-language programmers can use the Pascal
  16313.                          routines for opening AppleTalk. They can also check
  16314.                          the availability of port B themselves and then decide
  16315.                          whether to open MPP or ATP. Detailed information on
  16316.                          how to do this is provided in the section “Calling
  16317.                          the AppleTalk Manager from Assembly Language”.
  16318.  
  16319. The two AppleTalk device drivers, named .MPP and .ATP, are included in the 128K ROM.
  16320. The AppleTalk Manager, however (the interface to the drivers), is not in ROM; your
  16321. application must link to the appropriate object files.
  16322.  
  16323. On the Macintosh Plus, you need only open the .MPP driver; this will also load the
  16324. .ATP driver and NBP code automatically. Since, in the 128K ROM, device drivers return
  16325. errors, it’s no longer necessary to check whether port B is free and configured for
  16326. AppleTalk. If port B isn’t available, the .MPP driver won’t open and the result code
  16327. portInUse or portNotCf will be returned.
  16328.  
  16329. Assembly-language note:  When called from assembly language, the Datagram
  16330.                          Delivery Protocol (DDP) allows 14 (instead of 12)
  16331.                          open sockets.
  16332.  
  16333. The changes to the AppleTalk manager increase functionality and resources. Two interfaces
  16334. for the AppleTalk Manager calls are discussed: the new or preferred interface and the
  16335. alternate interface. Picking a node address in the server range, sending packets to
  16336. one’s own node, multiple concurrent NBP requests, sending ATP requests through a
  16337. specified socket and two new ATP calls are also discussed in this section. These
  16338. calls can only be made with the preferred interface.
  16339.  
  16340. _______________________________________________________________________________
  16341.  
  16342.  
  16343. æKY Calling…the…AppleTalk…Manager…from…Pascal
  16344. æC »CALLING THE APPLETALK MANAGER FROM PASCAL                AppleTalkManager
  16345. _______________________________________________________________________________
  16346.  
  16347. This section discusses how to use the AppleTalk Manager from Pascal. Equivalent
  16348. assembly-language information is given in the “Calling the AppleTalk Manager from
  16349. Assembly Language” section.
  16350.  
  16351. You can execute many AppleTalk Manager routines either synchronously (meaning that
  16352. the application can’t continue until the routine is completed) or asynchronously
  16353. (meaning that the application is free to perform other tasks while the routine is
  16354. being executed).
  16355.  
  16356. When an application calls an AppleTalk Manager routine asynchronously, an I/O request
  16357. is placed in the appropriate driver’s I/O queue, and control returns to the calling
  16358. program—possibly even before the actual I/O is completed. Requests are taken from the
  16359. queue one at a time, and processed; meanwhile, the calling program is free to work on
  16360. other things.
  16361.  
  16362. The routines that can be executed asynchronously contain a Boolean parameter called
  16363. async. If async is TRUE, the call is executed asynchronously; otherwise the call is
  16364. executed synchronously. Every time an asynchronous routine call is completed, the
  16365. AppleTalk Manager posts a network event. The message field of the event record will
  16366. contain a handle to the parameter block that was used to make that call.
  16367.  
  16368. Most AppleTalk Manager routines return an integer result code of type OSErr. Each
  16369. routine description lists all of the applicable result codes generated by the AppleTalk
  16370. Manager, along with a short description of what the result code means. Lengthier
  16371. explanations of all the result codes can be found in the summary at the end of the
  16372. chapter. Result codes from other parts of the Operating System may also be returned.
  16373. (See Appendix A for a list of all result codes.)
  16374.  
  16375. Many Pascal calls to the AppleTalk Manager require information passed in a parameter
  16376. block of type ABusRecord. The exact content of an ABusRecord depends on the protocol
  16377. being called:
  16378.  
  16379. TYPE  ABProtoType  =  (lapProto,ddpProto,nbpProto,atpProto);
  16380.       ABusRecord   =  RECORD
  16381.                         abOpcode:        ABCallType; {type of call}
  16382.                         abResult:        INTEGER;    {result code}
  16383.                         abUserReference: LONGINT;    {for your use}
  16384.                         CASE ABProtoType OF
  16385.                           lapProto:
  16386.                             . . .     {ALAP parameters}
  16387.                           ddpProto:
  16388.                             . . .     {DDP parameters}
  16389.                           nbpProto:
  16390.                             . . .     {NBP parameters}
  16391.                           atpProto:
  16392.                             . . .     {ATP parameters}
  16393.                         END;
  16394.                       END;
  16395.  
  16396.       ABRecPtr     = ^ABusRecord;
  16397.       ABRecHandle  = ^ABRecPtr;
  16398.  
  16399. The value of the abOpcode field is inserted by the AppleTalk Manager when the call is
  16400. made, and is always a member of the following set:
  16401.  
  16402. TYPE  ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,
  16403.                     tNBPConfirm,tNBPRegister,tATPSndRequest,
  16404.                     tATPGetRequest,tATPSdRsp,tATPAddRsp,tATPRequest,
  16405.                     tATPRespond);
  16406.  
  16407. The abUserReference field is available for use by the calling program in any way it
  16408. wants. This field isn’t used by the AppleTalk Manager routines or drivers.
  16409.  
  16410. The size of an ABusRecord data structure in bytes is given by one of the following
  16411. constants:
  16412.  
  16413. CONST  lapSize = 20;
  16414.        ddpSize = 26;
  16415.        nbpSize = 26;
  16416.        atpSize = 56;
  16417.  
  16418. Variables of type ABusRecord must be allocated in the heap with Memory Manager NewHandle
  16419. calls. For example:
  16420.  
  16421.   myABRecord := ABRecHandle(NewHandle(ddpSize))
  16422.  
  16423. Warning:  These Memory Manager calls can’t be made inside interrupts.
  16424.  
  16425. Routines that are executed asynchronously return control to the calling program with
  16426. the result code noErr as soon as the call is placed in the driver’s I/O queue. This
  16427. isn’t an indication of successful call completion; it simply indicates that the call
  16428. was successfully queued to the appropriate driver. To determine when the call is
  16429. actually completed, you can either check for a network event or poll the abResult
  16430. field of the call’s ABusRecord. The abResult field, set to 1 when the call is made,
  16431. receives the actual result code upon completion of the call.
  16432.  
  16433. Warning:  A data structure of type ABusRecord is often used by the AppleTalk
  16434.           Manager during an asynchronous call, and so is locked by the
  16435.           AppleTalk Manager. Don’t attempt to unlock or use such a variable.
  16436.  
  16437. Each routine description includes a list of the ABusRecord fields affected by the
  16438. routine. The arrow next to each field name indicates whether it’s an input, output,
  16439. or input/output parameter:
  16440.  
  16441. Arrow    Meaning
  16442.   -->    Parameter is passed to the routine
  16443.   <--    Parameter is returned by the routine
  16444.   <->    Parameter is passed to and returned by the routine
  16445.  
  16446. _______________________________________________________________________________
  16447.  
  16448. »Opening and Closing AppleTalk
  16449.  
  16450. •••Refer to Technical Note #224:•••
  16451.  
  16452. FUNCTION MPPOpen :  OSErr; [Not in ROM]
  16453.  
  16454. MPPOpen first checks whether the .MPP driver has already been loaded; if it has,
  16455. MPPOpen does nothing and returns noErr. If MPP hasn’t been loaded, MPPOpen attempts
  16456. to load it into the system heap. If it succeeds, it then initializes the driver’s
  16457. variables and goes through the process of dynamically assigning a node ID to that
  16458. Macintosh. On a Macintosh 512K or XL, it also loads the .ATP driver and NBP code into
  16459. the system heap.
  16460.  
  16461. If serial port B isn’t configured for AppleTalk, or is already in use, the .MPP
  16462. driver isn’t loaded and an appropriate result code is returned.
  16463.  
  16464. Result codes    noErr        No error
  16465.                 portInUse    Port B is already in use
  16466.                 portNotCf    Port B not configured for AppleTalk
  16467.  
  16468. FUNCTION MPPClose :  OSErr; [Not in ROM]
  16469.  
  16470. MPPClose removes the .MPP driver, and any data structures associated with it, from
  16471. memory. If the .ATP driver or NBP code were also installed, they’re removed as well.
  16472. MPPClose also returns the use of port B to the Serial Driver.
  16473.  
  16474. Warning:  Since other co-resident programs may be using AppleTalk, it’s
  16475.           strongly recommended that you never use this call. MPPClose will
  16476.           completely disable AppleTalk; the only way to restore AppleTalk
  16477.           is to call MPPOpen again.
  16478.  
  16479. _______________________________________________________________________________
  16480.  
  16481. »AppleTalk Link Access Protocol
  16482.  
  16483. »Data Structures
  16484.  
  16485. ALAP calls use the following ABusRecord fields:
  16486.  
  16487. lapProto:
  16488.     (lapAddress:    LAPAdrBlock; {destination or source node ID}
  16489.      lapReqCount:   INTEGER;     {length of frame data or buffer size in bytes}
  16490.      lapActCount:   INTEGER;     {number of frame data bytes actually received}
  16491.      lapDataPtr:    Ptr);        {pointer to frame data or pointer to buffer}
  16492.  
  16493. When an ALAP frame is sent, the lapAddress field indicates the ID of the destination
  16494. node. When an ALAP frame is received, lapAddress returns the ID of the source node.
  16495. The lapAddress field also indicates the ALAP protocol type of the frame:
  16496.  
  16497. TYPE  LAPAdrBlock = PACKED RECORD
  16498.                       dstNodeID:    Byte;  {destination node ID}
  16499.                       srcNodeID:    Byte;  {source node ID}
  16500.                       lapProtType:  ABByte {ALAP protocol type}
  16501.                     END;
  16502.  
  16503. When an ALAP frame is sent, lapReqCount indicates the size of the frame data in bytes
  16504. and lapDataPtr points to a buffer containing the frame data to be sent. When an ALAP
  16505. frame is received, lapDataPtr points to a buffer in which the incoming data can be
  16506. stored and lapReqCount indicates the size of the buffer in bytes. The number of bytes
  16507. actually sent or received is returned in the lapActCount field.
  16508.  
  16509. Each ALAP frame contains an eight-bit ALAP protocol type in the header. ALAP protocol
  16510. types 128 through 255 are reserved for internal use by ALAP, hence the declaration:
  16511.  
  16512. TYPE  ABByte = 1..127; {ALAP protocol type}
  16513.  
  16514. Warning:  Don’t use ALAP protocol type values 1 and 2; they’re reserved
  16515.           for use by DDP. Value 3 through 15 are reserved for internal
  16516.           use by Apple and also shouldn’t be used.
  16517.  
  16518. »Using ALAP
  16519.  
  16520. Most programs will never need to call ALAP, because higher-level protocols will
  16521. automatically call it as necessary. If you do want to send a frame directly via ALAP,
  16522. call the LAPWrite function. If you want to read ALAP frames, you have two choices:
  16523.  
  16524.   •  Call LAPOpenProtocol with NIL for protoPtr (see below); this installs
  16525.      the default protocol handler provided by the AppleTalk Manager. Then
  16526.      call LAPRead to receive frames.
  16527.   •  Write your own protocol handler, and call LAPOpenProtocol to add it
  16528.      to the node’s protocol handler table. The ALAP code will examine every
  16529.      incoming frame and send all those with the correct ALAP protocol type
  16530.      to your protocol handler. See the section “Protocol Handlers and Socket
  16531.      Listeners” for information on how to write a protocol handler.
  16532.  
  16533. When your program no longer wants to receive frames with a particular ALAP protocol
  16534. type value, it can call LAPCloseProtocol to remove the corresponding protocol handler
  16535. from the protocol handler table.
  16536.  
  16537. »ALAP Routines
  16538.  
  16539. FUNCTION LAPOpenProtocol (theLAPType:  ABByte;
  16540.                           protoPtr:  Ptr) :  OSErr; [Not in ROM]
  16541.  
  16542. LAPOpenProtocol adds the ALAP protocol type specified by theLAPType to the
  16543. node’s protocol table. If you provide a pointer to a protocol handler in protoPtr,
  16544. ALAP will send each frame with an ALAP protocol type of theLAPType to that protocol
  16545. handler.
  16546.  
  16547. If protoPtr is NIL, the default protocol handler will be used for receiving frames
  16548. with an ALAP protocol type of theLAPType. In this case, to receive a frame you must
  16549. call LAPRead to provide the default protocol handler with a buffer for placing the
  16550. data. If, however, you’ve written your own protocol handler and protoPtr points to
  16551. it, your protocol handler will have the responsibility for receiving the frame and
  16552. it’s not necessary to call LAPRead.
  16553.  
  16554. Result codes    noErr         No error
  16555.                 lapProtErr    Error attaching protocol type
  16556.  
  16557. FUNCTION LAPCloseProtocol (theLAPType:  ABByte) :  OSErr; [Not in ROM]
  16558.  
  16559. LAPCloseProtocol removes from the node’s protocol table the specified ALAP protocol
  16560. type, as well as its protocol handler.
  16561.  
  16562. Warning:  Don’t close ALAP protocol type values 1 or 2. If you close these
  16563.           protocol types, DDP will be disabled; once disabled, the only way
  16564.           to restore DDP is to restart the system, or to close and then
  16565.           reopen AppleTalk.
  16566.  
  16567. Result codes    noErr         No error
  16568.                 lapProtErr    Error detaching protocol type
  16569.  
  16570. FUNCTION LAPWrite (abRecord:  ABRecHandle;
  16571.                    async:  BOOLEAN) :  OSErr; [Not in ROM]
  16572.  
  16573. ABusRecord
  16574.   <--    abOpcode                {always tLAPWrite}
  16575.   <--    abResult                {result code}
  16576.   -->    abUserReference         {for your use}
  16577.   -->    lapAddress.dstNodeID    {destination node ID}
  16578.   -->    lapAddress.lapProtType  {ALAP protocol type}
  16579.   -->    lapReqCount             {length of frame data}
  16580.   -->    lapDataPtr              {pointer to frame data}
  16581.  
  16582. LAPWrite sends a frame to another node. LAPReqCount and lapDataPtr specify the length
  16583. and location of the data to send. The lapAddress.lapProtType field indicates the ALAP
  16584. protocol type of the frame and the lapAddress.dstNodeID indicates the node ID of the
  16585. node to which the frame should be sent.
  16586.  
  16587. Note:  The first two bytes of an ALAP frame’s data must contain the length
  16588.        in bytes of that data, including the length bytes themselves.
  16589.  
  16590. Result codes    noErr            No error
  16591.                 excessCollsns    Unable to contact destination node;
  16592.                                  packet not sent
  16593.                 ddpLenErr        ALAP data length too big
  16594.                 lapProtErr       Invalid ALAP protocol type
  16595.  
  16596. FUNCTION LAPRead (abRecord:  ABRecHandle;
  16597.                   async:  BOOLEAN) :  OSErr; [Not in ROM]
  16598.  
  16599. ABusRecord
  16600.   <--    abOpcode                {always tLAPRead}
  16601.   <--    abResult                {result code}
  16602.   -->    abUserReference         {for your use}
  16603.   <--    lapAddress.dstNodeID    {destination node ID}
  16604.   <--    lapAddress.srcNodeID    {source node ID}
  16605.   -->    lapAddress.lapProtType  {ALAP protocol type}
  16606.   -->    lapReqCount             {buffer size in bytes}
  16607.   <--    lapActCount             {number of frame data bytes actually received}
  16608.   -->    lapDataPtr              {pointer to buffer}
  16609.  
  16610. LAPRead receives a frame from another node. LAPReqCount and lapDataPtr specify the
  16611. size and location of the buffer that will receive the frame data. If the buffer isn’t
  16612. large enough to hold all of the incoming frame data, the extra bytes will be discarded
  16613. and buf2SmallErr will be returned. The number of bytes actually received is returned
  16614. in lapActCount. Only frames with ALAP protocol type equal to lapAddress.lapProtType
  16615. will be received. The node IDs of the frame’s source and destination nodes are returned
  16616. in lapAddress.srcNodeID and lapAddress.dstNodeID. You can determine whether the
  16617. packet was broadcast to you by examining the value of lapAddress.dstNodeID—if the
  16618. packet was broadcast it’s equal to 255, otherwise it’s equal to your node ID.
  16619.  
  16620. Note:  You should issue LAPRead calls only for ALAP protocol types that were
  16621.        opened (via LAPOpenProtocol) to use the default protocol handler.
  16622.  
  16623. Warning:  If you close a protocol type for which there are still LAPRead
  16624.           calls pending, the calls will be canceled but the memory occupied
  16625.           by their ABusRecords will not be released. For this reason, before
  16626.           closing a protocol type, call LAPRdCancel to cancel any pending
  16627.           LAPRead calls associated with that protocol type.
  16628.  
  16629. Result codes    noErr           No error
  16630.                 buf2SmallErr    Frame too large for buffer
  16631.                 readQErr        Invalid protocol type or protocol type not
  16632.                                 found in table
  16633.  
  16634. FUNCTION LAPRdCancel (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  16635.  
  16636. Given the handle to the ABusRecord of a previously made LAPRead call, LAPRdCancel
  16637. dequeues the LAPRead call, provided that a packet satisfying the LAPRead has not
  16638. already arrived. LAPRdCancel returns noErr if the LAPRead call is successfully removed
  16639. from the queue. If LAPRdCancel returns recNotFnd, check the abResult field to verify
  16640. that the LAPRead has been completed and determine its outcome.
  16641.  
  16642. Result codes    noErr        No error
  16643.                 readQErr     Invalid protocol type or protocol type not
  16644.                              found in table
  16645.                 recNotFnd    ABRecord not found in queue
  16646.  
  16647. »Example
  16648.  
  16649. This example sends an ALAP packet synchronously and waits asynchronously for a response.
  16650. Assume that both nodes are using a known protocol type (in this case, 73) to receive
  16651. packets, and that the destination node has a node ID of 4.
  16652.  
  16653. VAR
  16654.   myABRecord: ABRecHandle;
  16655.   myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
  16656.   myLAPType: Byte;
  16657.   errCode, index, dataLen: INTEGER;
  16658.   someText: Str255;
  16659.   async: BOOLEAN;
  16660.  
  16661. BEGIN
  16662.   errCode := MPPOpen;
  16663.   IF errCode <> noErr THEN
  16664.     WRITELN('Error in opening AppleTalk')
  16665.     {Maybe serial port B isn't available for use by AppleTalk}
  16666.   ELSE
  16667.     BEGIN
  16668.     {Call Memory Manager to allocate ABusRecord}
  16669.     myABRecord := ABRecHandle(NewHandle(lapSize));
  16670.     myLAPType := 73;
  16671.    {Enter myLAPType into protocol handler table and install default handler to }
  16672.     { service frames of that ALAP type. No packets of that ALAP type will be }
  16673.     { received until we call LAPRead.}
  16674.     errCode := LAPOpenProtocol(myLAPType, NIL);
  16675.     IF errCode <> noErr THEN
  16676.       WRITELN('Error while opening the protocol type')
  16677.       {Have we opened too many protocol types? Remember that DDP uses two of }
  16678.       { them.}
  16679.     ELSE
  16680.       BEGIN
  16681.       {Prepare data to be sent}
  16682.       someText := 'This data will be in the ALAP data area';
  16683.       {The .MPP implementation requires that the first two bytes of the ALAP }
  16684.       { data field contain the length of the data, including the length bytes }
  16685.       { themselves.}
  16686.       dataLen := LENGTH(someText) + 2;
  16687.       buffer[0] := CHR(dataLen DIV 256); {high byte of data length}
  16688.       buffer[1] := CHR(dataLen MOD 256); {low byte of data length}
  16689.       FOR index := 1 TO dataLen - 2 DO {stuff buffer with packet data}
  16690.         buffer[index + 1] := someText[index];
  16691.       async := FALSE;
  16692.       WITH myABRecord^^ DO {fill parameters in the ABusRecord}
  16693.         BEGIN
  16694.         lapAddress.lapProtType := myLAPType;
  16695.         lapAddress.dstNodeID := 4;
  16696.         lapReqCount := dataLen;
  16697.         lapDataPtr := @buffer;
  16698.         END;
  16699.       {Send the frame}
  16700.       errCode := LAPWrite(myABRecord, async);
  16701.       {In the case of a sync call, errCode and the abResult field of }
  16702.       { the myABRecord will contain the same result code. We can also }
  16703.       { reuse myABRecord, since we know whether the call has completed.}
  16704.       IF errCode <> noErr THEN
  16705.         WRITELN('Error while writing out the packet')
  16706.         {Maybe the receiving node wasn't on-line}
  16707.       ELSE
  16708.         BEGIN
  16709.         {We have sent out the packet and are now waiting for a response. We }
  16710.         { issue an async LAPRead call so that we don't “hang” waiting for a }
  16711.         { response that may not come.}
  16712.         async := TRUE;
  16713.         WITH myABRecord^^ DO
  16714.           BEGIN
  16715.           lapAddress.lapProtType := myLAPType;
  16716.           {ALAP type we want to receive }
  16717.           lapReqCount := 600; {our buffer is maximum size}
  16718.           lapDataPtr := @buffer;
  16719.           END;
  16720.         errCode := LAPRead(myABRecord, async); {wait for a packet}
  16721.         IF errCode <> noErr THEN
  16722.           WRITELN('Error while trying to queue up a LAPRead')
  16723.           {Was the protocol handler installed correctly?}
  16724.         ELSE
  16725.           BEGIN
  16726.           {We can either sit here in a loop and poll the abResult }
  16727.           { field or just exit our code and use the event }
  16728.           { mechanism to flag us when the packet arrives.}
  16729.           CheckForMyEvent; {your procedure for checking for a network event}
  16730.           errCode := LAPCloseProtocol(myLAPType);
  16731.           IF errCode <> noErr THEN
  16732.             WRITELN('Error while closing the protocol type');
  16733.           END;
  16734.         END;
  16735.       END;
  16736.     END;
  16737. END.
  16738.  
  16739.  
  16740. _______________________________________________________________________________
  16741.  
  16742. »Datagram Delivery Protocol
  16743.  
  16744. »Data Structures
  16745.  
  16746. DDP calls use the following ABusRecord fields:
  16747.  
  16748. ddpProto:
  16749.     (ddpType:      Byte;       {DDP protocol type}
  16750.      ddpSocket:    Byte;       {source or listening socket number}
  16751.      ddpAddress:   AddrBlock;  {destination or source socket address}
  16752.      ddpReqCount:  INTEGER;    {length of datagram data or buffer size in bytes}
  16753.      ddpActCount:  INTEGER;    {number of bytes actually received}
  16754.      ddpDataPtr:   Ptr;        {pointer to buffer}
  16755.      ddpNodeID:    Byte);      {original destination node ID}
  16756.  
  16757. When a DDP datagram is sent, ddpReqCount indicates the size of the datagram data in
  16758. bytes and ddpDataPtr points to a buffer containing the datagram data. DDPSocket
  16759. specifies the socket from which the datagram should be sent. DDPAddress is the internet
  16760. address of the socket to which the datagram should be sent:
  16761.  
  16762. TYPE  AddrBlock = PACKED RECORD
  16763.                     aNet:     INTEGER;  {network number}
  16764.                     aNode:    Byte;     {node ID}
  16765.                     aSocket:  Byte      {socket number}
  16766.                   END;
  16767.  
  16768. Note:  The network number you specify in ddpAddress.aNet tells MPP whether
  16769.        to create a long header (for an internet) or a short header (for a
  16770.        local network only). A short DDP header will be sent if ddpAddress.aNet
  16771.        is 0 or equal to the network number of the local network.
  16772.  
  16773. When a DDP datagram is received, ddpDataPtr points to a buffer in which the incoming
  16774. data can be stored and ddpReqCount indicates the size of the buffer in bytes. The
  16775. number of bytes actually sent or received is returned in the ddpActCount field.
  16776. DDPAddress is the internet address of the socket from which the datagram was sent.
  16777.  
  16778. DDPType is the DDP protocol type of the datagram, and ddpSocket specifies the socket
  16779. that will receive the datagram.
  16780.  
  16781. Warning:  DDP protocol types 1 through 15 and DDP socket numbers 1 through 63
  16782.           are reserved by Apple for internal use. Socket numbers 64 through 127
  16783.           are available for experimental use. Use of these experimental sockets
  16784.           isn’t recommended for commercial products, since there’s no mechanism
  16785.           for eliminating conflicting usage by different developers.
  16786.  
  16787. »Using DDP
  16788.  
  16789. Before it can use a socket, the program must call DDPOpenSocket, which adds a socket
  16790. and its socket listener to the socket table. When a program is finished using a
  16791. socket, call DDPCloseSocket, which removes the socket’s entry from the socket table.
  16792. To send a datagram via DDP, call DDPWrite. To receive datagrams, you have two choices:
  16793.  
  16794.   •  Call DDPOpenSocket with NIL for sktListener (see below); this installs
  16795.      the default socket listener provided by the AppleTalk Manager. Then call
  16796.      DDPRead to receive datagrams.
  16797.   •  Write your own socket listener and call DDPOpenSocket to install it. DDP
  16798.      will call your socket listener for every incoming datagram for that
  16799.      socket; in this case, you shouldn’t call DDPRead. For information on how
  16800.      to write a socket listener, see the section “Protocol Handlers and Socket
  16801.      Listeners”.
  16802.  
  16803. To cancel a previously issued DDPRead call (provided it’s still in the queue), call
  16804. DDPRdCancel.
  16805.  
  16806. »DDP Routines
  16807.  
  16808. FUNCTION DDPOpenSocket (VAR theSocket:  Byte;
  16809.                         sktListener:  Ptr) :  OSErr; [Not in ROM]
  16810.  
  16811. DDPOpenSocket adds a socket and its socket listener to the socket table. If theSocket
  16812. is nonzero, it must be in the range 64 to 127, and it specifies the socket’s number;
  16813. if theSocket is 0, DDPOpenSocket dynamically assigns a socket number in the range 128
  16814. to 254, and returns it in theSocket. SktListener contains a pointer to the socket
  16815. listener; if it’s NIL, the default listener will be used.
  16816.  
  16817. If you’re using the default socket listener, you must then call DDPRead to receive a
  16818. datagram (in order to specify buffer space for the default socket listener). If,
  16819. however, you’ve written your own socket listener and sktListener points to it, your
  16820. listener will provide buffers for receiving datagrams and you shouldn’t use DDPRead
  16821. calls.
  16822.  
  16823. DDPOpenSocket will return ddpSktErr if you pass the number of an already opened
  16824. socket, if you pass a socket number greater than 127, or if the socket table is
  16825. full.
  16826.  
  16827. Note:  The range of static socket numbers 1 through 63 is reserved by Apple
  16828.        for internal use. Socket numbers 64 through 127 are available for
  16829.        unrestricted experimental use.
  16830.  
  16831. Result codes    noErr        No error
  16832.                 ddpSktErr    Socket error
  16833.  
  16834. FUNCTION DDPCloseSocket (theSocket:  Byte) :  OSErr; [Not in ROM]
  16835.  
  16836. DDPCloseSocket removes the entry of the specified socket from the socket table and
  16837. cancels all pending DDPRead calls that have been made for that socket. If you pass a
  16838. socket number of 0, or if you attempt to close a socket that isn’t open, DDPCloseSocket
  16839. will return ddpSktErr.
  16840.  
  16841. Result codes    noErr        No error
  16842.                 ddpSktErr    Socket error
  16843.  
  16844. FUNCTION DDPWrite (abRecord:  ABRecHandle; doChecksum:  BOOLEAN;
  16845.                    async:  BOOLEAN) :  OSErr; [Not in ROM]
  16846.  
  16847. ABusRecord
  16848.   <--    abOpcode         {always tDDPWrite}
  16849.   <--    abResult         {result code}
  16850.   -->    abUserReference  {for your use}
  16851.   -->    ddpType          {DDP protocol type}
  16852.   -->    ddpSocket        {source socket number}
  16853.   -->    ddpAddress       {destination socket address}
  16854.   -->    ddpReqCount      {length of datagram data}
  16855.   -->    ddpDataPtr       {pointer to buffer}
  16856.  
  16857. DDPWrite sends a datagram to another socket. DDPReqCount and ddpDataPtr specify the
  16858. length and location of the data to send. The ddpType field indicates the DDP protocol
  16859. type of the frame, and ddpAddress is the complete internet address of the socket to
  16860. which the datagram should be sent. DDPSocket specifies the socket from which the
  16861. datagram should be sent. Datagrams sent over the internet to a node on an AppleTalk
  16862. network different from the sending node’s network have an optional software checksum
  16863. to detect errors that might occur inside the intermediate bridges. If doChecksum is
  16864. TRUE, DDPWrite will compute this checksum; if it’s FALSE, this software checksum
  16865. feature is ignored.
  16866.  
  16867. Note:  The destination socket can’t be in the same node as the program
  16868.        making the DDPWrite call.
  16869.  
  16870. Result codes    noErr          No error
  16871.                 ddpLenErr      Datagram length too big
  16872.                 ddpSktErr      Source socket not open
  16873.                 noBridgeErr    No bridge found
  16874.  
  16875. FUNCTION DDPRead (abRecord:  ABRecHandle; retCksumErrs:  BOOLEAN;
  16876.                   async:  BOOLEAN) :  OSErr; [Not in ROM]
  16877.  
  16878. ABusRecord
  16879.   <--    abOpcode         {always tDDPRead}
  16880.   <--    abResult         {result code}
  16881.   -->    abUserReference  {for your use}
  16882.   <--    ddpType          {DDP protocol type}
  16883.   -->    ddpSocket        {listening socket number}
  16884.   <--    ddpAddress       {source socket address}
  16885.   -->    ddpReqCount      {buffer size in bytes}
  16886.   <--    ddpActCount      {number of bytes actually received}
  16887.   -->    ddpDataPtr       {pointer to buffer}
  16888.   <--    ddpNodeID        {original destination node ID}
  16889.  
  16890. DDPRead receives a datagram from another socket. The size and location of the buffer
  16891. that will receive the data are specified by ddpReqCount and ddpDataPtr. If the buffer
  16892. isn’t large enough to hold all of the incoming frame data, the extra bytes will be
  16893. discarded and buf2SmallErr will be returned. The number of bytes actually received is
  16894. returned in ddpActCount. DDPSocket specifies the socket to receive the datagram (the
  16895. “listening” socket). The node to which the packet was sent is returned in ddpNodeID;
  16896. if the packet was broadcast ddpNodeID will contain 255. The address of the socket
  16897. that sent the packet is returned in ddpAddress. If retCksumErrs is FALSE, DDPRead
  16898. will discard any packets received with an invalid checksum and inform the caller of
  16899. the error. If retCksumErrs is TRUE, DDPRead will deliver all packets, whether or not
  16900. the checksum is valid; it will also notify the caller when there’s a checksum error.
  16901.  
  16902. Note:  The sender of the datagram must be in a different node from the
  16903.        receiver. You should issue DDPRead calls only for receiving datagrams
  16904.        for sockets opened with the default socket listener; see the
  16905.        description of DDPOpenSocket.
  16906.  
  16907. Note:  If the buffer provided isn’t large enough to hold all of the incoming
  16908.        frame data (buf2SmallErr), the checksum can’t be calculated; in this
  16909.        case, DDPRead will deliver packets even if retCksumErrs is FALSE.
  16910.  
  16911. Result codes    noErr           No error
  16912.                 buf2SmallErr    Datagram too large for buffer
  16913.                 cksumErr        Checksum error
  16914.                 ddpLenErr       Datagram length too big
  16915.                 ddpSktErr       Socket error
  16916.                 readQErr        Invalid socket or socket not found in table
  16917.  
  16918. FUNCTION DDPRdCancel (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  16919.  
  16920. Given the handle to the ABusRecord of a previously made DDPRead call, DDPRdCancel
  16921. dequeues the DDPRead call, provided that a packet satisfying the DDPRead hasn’t
  16922. already arrived. DDPRdCancel returns noErr if the DDPRead call is successfully removed
  16923. from the queue. If DDPRdCancel returns recNotFnd, check the abResult field of abRecord
  16924. to verify that the DDPRead has been completed and determine its outcome.
  16925.  
  16926. Result codes    noErr        No error
  16927.                 readQErr     Invalid socket or socket not found in table
  16928.                 recNotFnd    ABRecord not found in queue
  16929.  
  16930. »Example
  16931.  
  16932. This example sends a DDP packet synchronously and waits asynchronously for a response.
  16933. Assume that both nodes are using a known socket number (in this case, 30) to receive
  16934. packets. Normally, you would want to use NBP to look up your destination’s socket
  16935. address.
  16936.  
  16937. VAR
  16938.   myABRecord: ABRecHandle;
  16939.   myBuffer: PACKED ARRAY [0..599] OF CHAR; {buffer for both send and receive}
  16940.   mySocket: Byte;
  16941.   errCode, index, dataLen: INTEGER;
  16942.   someText: Str255;
  16943.   async, retCksumErrs, doChecksum: BOOLEAN;
  16944.  
  16945. BEGIN
  16946.   errCode := MPPOpen;
  16947.   IF errCode <> noErr THEN
  16948.     WRITELN('Error in opening AppleTalk')
  16949.     {Maybe serial port B isn't available for use by AppleTalk}
  16950.   ELSE
  16951.     BEGIN
  16952.       {Call Memory Manager to allocate ABusRecord}
  16953.       myABRecord := ABRecHandle(NewHandle(ddpSize));
  16954.       mySocket := 30;
  16955.   {Add mySocket to socket table and install default socket listener to service }
  16956. { datagrams addressed to that socket. No packets addressed to mySocket will be }
  16957.       { received until we call DDPRead. }
  16958.       errCode := DDPOpenSocket(mySocket, NIL);
  16959.       IF errCode <> noErr THEN
  16960.         WRITELN('Error while opening the socket')
  16961.       {Have we opened too many socket listeners? Remember that DDP uses two of }
  16962.         { them.}
  16963.       ELSE
  16964.         BEGIN
  16965.           {Prepare data to be sent}
  16966.           someText := 'This is a sample datagram';
  16967.           dataLen := LENGTH(someText);
  16968.           FOR index := 0 TO dataLen - 1 DO {stuff buffer with packet data}
  16969.             myBuffer[index] := someText[index + 1];
  16970.           async := FALSE;
  16971.           WITH myABRecord^^ DO {fill the parameters in the ABusRecord}
  16972.             BEGIN
  16973.               ddpType := 5;
  16974.               ddpAddress.aNet := 0; {send on “our” network}
  16975.               ddpAddress.aNode := 34;
  16976.               ddpAddress.aSocket := mySocket;
  16977.               ddpReqCount := dataLen;
  16978.               ddpDataPtr := @myBuffer;
  16979.             END;
  16980.           doChecksum := FALSE;
  16981.     {If packet contains a DDP long header, compute checksum and insert it into }
  16982.           { the header.}
  16983.           errCode := DDPWrite(myABRecord, doChecksum, async); {send packet}
  16984.      {In the case of a sync call, errCode and the abResult field of myABRecord }
  16985.    { will contain the same result code. We can also reuse myABRecord, since we }
  16986.           { know whether the call has completed.}
  16987.           IF errCode <> noErr THEN
  16988.             WRITELN('Error while writing out the packet')
  16989.             {Maybe the receiving node wasn't on-line}
  16990.           ELSE
  16991.             BEGIN
  16992.            {We have sent out the packet and are now waiting for a response. We }
  16993.            { issue an async DDPRead call so that we don't “hang” waiting for a }
  16994.           { response that may not come. To cancel the async read call, we must }
  16995.               { close the socket associated with the call or call DDPRdCancel.}
  16996.               async := TRUE;
  16997.               retCksumErrs := TRUE; {return packets even if }
  16998.                                     { they have a checksum error}
  16999.               WITH myABRecord^^ DO
  17000.                 BEGIN
  17001.                   ddpSocket := mySocket;
  17002.                   ddpReqCount := 600; {our reception buffer is max size}
  17003.                   ddpDataPtr := @myBuffer;
  17004.                 END;
  17005.               {Wait for a packet asynchronously}
  17006.               errCode := DDPRead(myABRecord, retCksumErrs, async);
  17007.               IF errCode <> noErr THEN
  17008.                 WRITELN('Error while trying to queue up a DDPRead')
  17009.                 {Was the socket listener installed correctly?}
  17010.               ELSE
  17011.                 BEGIN
  17012.                   {We can either sit here in a loop and poll the }
  17013.                   { abResult field or just exit our code and use the }
  17014.                   { event mechanism to flag us when the packet arrives.}
  17015.                   CheckForMyEvent; {your procedure for checking for a }
  17016.                                    { network event}
  17017.                   {If there were no errors, a packet is inside the array }
  17018.                   { mybuffer, the length is in ddpActCount, and the }
  17019.                   { address of the sending socket is in ddpAddress. }
  17020.                   { Process the packet received here and report any errors.}
  17021.                   errCode := DDPCloseSocket(mySocket); {we're done with it}
  17022.                   IF errCode <> noErr THEN
  17023.                     WRITELN('Error while closing the socket');
  17024.                 END;
  17025.             END;
  17026.         END;
  17027.     END;
  17028. END.
  17029.  
  17030. _______________________________________________________________________________
  17031.  
  17032. »AppleTalk Transaction Protocol
  17033.  
  17034. »Data Structures
  17035.  
  17036. ATP calls use the following ABusRecord fields:
  17037.  
  17038. atpProto:
  17039.   (atpSocket:     Byte;        {listening or responding socket number}
  17040.    atpAddress:    AddrBlock;   {destination or source socket address}
  17041.    atpReqCount:   INTEGER;     {request size or buffer size}
  17042.    atpDataPtr:    Ptr;         {pointer to buffer}
  17043.    atpRspBDSPtr:  BDSPtr;      {pointer to response BDS}
  17044.    atpBitMap:     BitMapType;  {transaction bit map}
  17045.    atpTransID:    INTEGER;     {transaction ID}
  17046.    atpActCount:   INTEGER;     {number of bytes actually received}
  17047.    atpUserData:   LONGINT;     {user bytes}
  17048.    atpXO:         BOOLEAN;     {exactly-once flag}
  17049.    atpEOM:        BOOLEAN;     {end-of-message flag}
  17050.    atpTimeOut:    Byte;        {retry timeout interval in seconds}
  17051.    atpRetries:    Byte;        {maximum number of retries}
  17052.    atpNumBufs:    Byte;        {number of elements in response BDS or number }
  17053.                                { of response packets sent}
  17054.    atpNumRsp:     Byte;        {number of response packets received or }
  17055.                                { sequence number}
  17056.    atpBDSSize:    Byte;        {number of elements in response BDS}
  17057.    atpRspUData:   LONGINT;     {user bytes sent or received in transaction }
  17058.                                { response}
  17059.    atpRspBuf:     Ptr;         {pointer to response message buffer}
  17060.    atpRspSize:    INTEGER);    {size of response message buffer}
  17061.   
  17062. The socket receiving the request or sending the response is identified by atpSocket.
  17063. ATPAddress is the address of either the destination or the source socket of a transaction,
  17064. depending on whether the call is sending or receiving data, respectively. ATPDataPtr
  17065. and atpReqCount specify the location and size
  17066. (in bytes) of a buffer that either contains a request or will receive a request. The
  17067. number of bytes actually received in a request is returned in atpActCount. ATPTransID
  17068. specifies the transaction ID. The transaction bit map is contained in atpBitMap, in
  17069. the form:
  17070.  
  17071. TYPE BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
  17072.  
  17073. Each bit in the bit map corresponds to one of the eight possible packets in a response.
  17074. For example, when a request is made for which five response packets are expected, the
  17075. bit map sent is binary 00011111 or decimal 31. If the second packet in the response
  17076. is lost, the requesting socket will retransmit the request with a bit map of binary
  17077. 00000010 or decimal 2.
  17078.  
  17079. ATPUserData contains the user bytes of an ATP header. ATPXO is TRUE if the transaction
  17080. is to be made with exactly-once service. ATPEOM is TRUE if the response packet is the
  17081. last packet of a transaction. If the number of responses is less than the number that
  17082. were requested, then ATPEOM must also be TRUE. ATPNumRsp contains either the number
  17083. of responses received or the sequence number of a response.
  17084.  
  17085. The timeout interval in seconds and the maximum number of times that a request should
  17086. be made are indicated by atpTimeOut and atpRetries, respectively.
  17087.  
  17088. Note:  Setting atpRetries to 255 will cause the request to be retransmitted
  17089.        indefinitely, until a full response is received or the call is canceled.
  17090.  
  17091. ATP provides a data structure, known as a response buffer data structure
  17092. (response BDS), for allocating buffer space to receive the datagram(s) of the response.
  17093. A response BDS is an array of one to eight elements. Each BDS element defines the
  17094. size and location of a buffer for receiving one response datagram; they’re numbered 0
  17095. to 7 to correspond to the sequence numbers of the response datagrams.
  17096.  
  17097. ATP needs a separate buffer for each response datagram expected, since packets may
  17098. not arrive in the proper sequence. It does not, however, require you to set up and
  17099. use the BDS data structure to describe the response buffers; if you
  17100. don’t, ATP will do it for you. Two sets of calls are provided for both requests and
  17101. responses; one set requires you to allocate a response BDS and the other doesn’t.
  17102.  
  17103. Assembly-language note:  The two calls that don’t require you to define a BDS
  17104.                          data structure (ATPRequest and ATPResponse) are
  17105.                          available in Pascal only.
  17106.  
  17107. The number of BDS elements allocated (in other words, the maximum number of datagrams
  17108. that the responder can send) is indicated in the TReq by an eight-bit bit map. The
  17109. bits of this bit map are numbered 0 to 7 (the least significant bit being number 0);
  17110. each bit corresponds to the response datagram with the respective sequence number.
  17111.  
  17112. ATPRspBDSPtr and atpBDSSize indicate the location and number of elements in the
  17113. response BDS, which has the following structure:
  17114.  
  17115. TYPE  BDSElement =
  17116.              RECORD
  17117.                buffSize:   INTEGER;  {buffer size in bytes}
  17118.                buffPtr:    Ptr;      {pointer to buffer}
  17119.                dataSize:   INTEGER;  {number of bytes actually received}
  17120.                userBytes:  LONGINT   {user bytes}
  17121.              END;
  17122.  
  17123.       BDSType = ARRAY[0..7] OF BDSElement; {response BDS}
  17124.       BDSPtr  = ^BDSType;
  17125.  
  17126. ATPNumBufs indicates the number of elements in the response BDS that contain information.
  17127. In most cases, you can allocate space for your variables of BDSType statically with a
  17128. VAR declaration. However, you can allocate only the minimum space required by your
  17129. ATP calls by doing the following:
  17130.  
  17131.   VAR myBDSPtr:  BDSPtr;
  17132.       . . .
  17133.   numOfBDS := 3; {number of elements needed}
  17134.   myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement) * numOfBDS));
  17135.  
  17136. Note:  The userBytes field of the BDSElement and the atpUserData field
  17137.        of the ABusRecord represent the same information in the datagram.
  17138.        Depending on the ATP call made, one or both of these fields will be used.
  17139.  
  17140. »Using ATP
  17141.  
  17142. Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
  17143. system resource file via an ATPLoad call. The .ATP driver loads itself into the
  17144. application heap and installs a task into the vertical retrace queue.
  17145.  
  17146. Warning:  When another application starts up, the application heap is
  17147.           reinitialized; on a Macintosh 128K, this means that the ATP
  17148.           code is lost (and must be reloaded by the next application).
  17149.  
  17150. When you’re through using ATP on a Macintosh 128K, call ATPUnload—the system will be
  17151. returned to the state it was in before the .ATP driver was opened.
  17152.  
  17153. On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
  17154. either at system startup or upon execution of MPPOpen or ATPLoad. ATPUnload has no
  17155. effect on a Macintosh 512K or XL.
  17156.  
  17157. To send a transaction request, call ATPSndRequest or ATPRequest. The .ATP driver will
  17158. automatically select and open a socket through which the request datagram will be
  17159. sent, and through which the response datagrams will be received. The requester must
  17160. specify the full network address (network number, node ID, and socket number) of the
  17161. socket to which the request is to be sent. This socket is known as the responding
  17162. socket, and its address must be known in advance by the requester.
  17163.  
  17164. At the responder’s end, before a transaction request can be received, a responding
  17165. socket must be opened, and the appropriate calls be made, to receive a request. To do
  17166. this, the responder first makes an ATPOpenSocket call which allows the responder to
  17167. specify the address (or part of it) of the requesters from whom it’s willing to
  17168. accept transaction requests. Then it issues an ATPGetRequest call to provide ATP with
  17169. a buffer for receiving a request; when a request is received, ATPGetRequest is completed.
  17170. The responder can queue up several ATPGetRequest calls, each of which will be completed
  17171. as requests are received.
  17172.  
  17173. Upon receiving a request, the responder performs the requested operation, and then
  17174. prepares the information to be returned to the requester. It then calls ATPSndRsp (or
  17175. ATPResponse) to send the response. Actually, the responder can issue the ATPSndRsp
  17176. call with only part (or none) of the response specified. Additional portions of the
  17177. response can be sent later by calling ATPAddRsp.
  17178.  
  17179. The ATPSndRsp and ATPAddRsp calls provide flexibility in the design (and range of
  17180. types) of transaction responders. For instance, the responder may, for some reason,
  17181. be forced to send the responses out of sequence. Also, there might be memory constraints
  17182. that force sending the complete transaction response in parts. Even though eight
  17183. response datagrams might need to be sent, the responder might have only enough memory
  17184. to build one datagram at a time. In this case, it would build the first response
  17185. datagram and call ATPSndRsp to send it. It would then build the second response
  17186. datagram in the same buffer and call ATPAddRsp to send it; and so on, for the third
  17187. through eighth response datagrams.
  17188.  
  17189. A responder can close a responding socket by calling ATPCloseSocket. This call cancels
  17190. all pending ATP calls for that socket, such as ATPGetRequest, ATPSndRsp, and ATPResponse.
  17191.  
  17192. For exactly-once transactions, the ATPSndRsp and ATPAddRsp calls don’t terminate
  17193. until the entire transaction has completed (that is, the responding end receives a
  17194. release packet, or the release timer has expired).
  17195.  
  17196. To cancel a pending, asynchronous ATPSndRequest or ATPRequest call, call ATPReqCancel.
  17197. To cancel a pending, asynchronous ATPSndRsp or ATPResponse call, call ATPRspCancel.
  17198. Pending asynchronous ATPGetRequest calls can be canceled only by issuing the ATPCloseSocket
  17199. call, but that will cancel all outstanding calls for that socket.
  17200.  
  17201. •••Refer to Technical Note #250:•••
  17202.  
  17203. Warning:  You cannot reuse a variable of type ABusRecord passed to an ATP
  17204.           routine until the entire transaction has either been completed
  17205.           or canceled.
  17206.  
  17207. »ATP Routines
  17208.  
  17209. FUNCTION ATPLoad :  OSErr; [Not in ROM]
  17210.  
  17211. •••Refer to Technical Note #224:•••
  17212.  
  17213. ATPLoad first verifies that the .MPP driver is loaded and running. If it isn’t,
  17214. ATPLoad verifies that port B is configured for AppleTalk and isn’t in use, and then
  17215. loads MPP into the system heap.
  17216.  
  17217. ATPLoad then loads the .ATP driver, unless it’s already in memory. On a Macintosh
  17218. 128K, ATPLoad reads the .ATP driver from the system resource file into the application
  17219. heap; on a Macintosh 512K or XL, ATP is read into the system heap.
  17220.  
  17221. Note:  On a Macintosh 512K or XL, ATPLoad and MPPOpen perform essentially
  17222.        the same function.
  17223.  
  17224. Result codes    noErr        No error
  17225.                 portInUse    Port B is already in use
  17226.                 portNotCf    Port B not configured for AppleTalk
  17227.  
  17228. FUNCTION ATPUnload :  OSErr; [Not in ROM]
  17229.  
  17230. ATPUnload makes the .ATP driver purgeable; the space isn’t actually released by the
  17231. Memory Manager until necessary.
  17232.  
  17233. Note:  This call applies only to a Macintosh 128K; on a Macintosh 512K
  17234.        or Macintosh XL, ATPUnload has no effect.
  17235.  
  17236. Result codes    noErr    No error
  17237.  
  17238. FUNCTION ATPOpenSocket (addrRcvd:  AddrBlock;
  17239.                         VAR atpSocket:  Byte) :  OSErr; [Not in ROM]
  17240.  
  17241. ATPOpenSocket opens a socket for the purpose of receiving requests. ATPSocket contains
  17242. the socket number of the socket to open; if it’s 0, a number is dynamically assigned
  17243. and returned in atpSocket. AddrRcvd contains a filter of the sockets from which
  17244. requests will be accepted. A 0 in the network number, node ID, or socket number field
  17245. of the addrRcvd record acts as a “wild card”; for instance, a 0 in the socket number
  17246. field means that requests will be accepted from all sockets in the node(s) specified
  17247. by the network and node fields.
  17248.  
  17249. Result codes    noErr          No error
  17250.                 tooManySkts    Socket table full
  17251.                 noDataArea     Too many outstanding ATP calls
  17252.  
  17253. Note:  If you’re only going to send requests and receive responses to
  17254.        these requests, you don’t need to open an ATP socket. When you
  17255.        make the ATPSndRequest or ATPRequest call, ATP automatically
  17256.        opens a dynamically assigned socket for that purpose.
  17257.  
  17258. FUNCTION ATPCloseSocket (atpSocket:  Byte) :  OSErr; [Not in ROM]
  17259.  
  17260. ATPCloseSocket closes the responding socket whose number is specified by atpSocket.
  17261. It releases the data structures associated with all pending, asynchronous calls
  17262. involving that socket; these pending calls are completed immediately and return the
  17263. result code sktClosed.
  17264.  
  17265. Result codes    noErr         No error
  17266.                 noDataArea    Too many outstanding ATP calls
  17267.  
  17268. FUNCTION ATPSndRequest (abRecord:  ABRecHandle;
  17269.                         async:  BOOLEAN) :  OSErr; [Not in ROM]
  17270.  
  17271. ABusRecord
  17272.   <--    abOpcode         {always tATPSndRequest}
  17273.   <--    abResult         {result code}
  17274.   -->    abUserReference  {for your use}
  17275.   -->    atpAddress       {destination socket address}
  17276.   -->    atpReqCount      {request size in bytes}
  17277.   -->    atpDataPtr       {pointer to buffer}
  17278.   -->    atpRspBDSPtr     {pointer to response BDS}
  17279.   -->    atpUserData      {user bytes}
  17280.   -->    atpXO            {exactly-once flag}
  17281.   <--    atpEOM           {end-of-message flag}
  17282.   -->    atpTimeOut       {retry timeout interval in seconds}
  17283.   -->    atpRetries       {maximum number of retries}
  17284.   -->    atpNumBufs       {number of elements in response BDS}
  17285.   <--    atpNumRsp        {number of response packets actually received}
  17286.  
  17287. ATPSndRequest sends a request to another socket. ATPAddress is the internet address
  17288. of the socket to which the request should be sent. ATPDataPtr and atpReqCount specify
  17289. the location and size of a buffer that contains the request information to be sent.
  17290. ATPUserData contains the user bytes for the ATP header.
  17291.  
  17292. ATPSndRequest requires you to allocate a response BDS. ATPRspBDSPtr is a pointer to
  17293. the response BDS; atpNumBufs indicates the number of elements in the BDS (this is
  17294. also the maximum number of response datagrams that will be accepted). The number of
  17295. response datagrams actually received is returned in atpNumRsp; if a nonzero value is
  17296. returned, you can examine the response BDS to determine which packets of the transaction
  17297. were actually received. If the number returned is less than requested, one of the
  17298. following is true:
  17299.  
  17300.   •  Some of the packets have been lost and the retry count has been exceeded.
  17301.   •  ATPEOM is TRUE; this means that the response consisted of fewer packets
  17302.      than were expected, but that all packets sent were received (the last
  17303.      packet came with the atpEOM flag set).
  17304.  
  17305. ATPTimeOut indicates the length of time that ATPSndRequest should wait for a response
  17306. before retransmitting the request. ATPRetries indicates the maximum number of retries
  17307. ATPSndRequest should attempt. ATPXO should be TRUE if you want the request to be part
  17308. of an exactly-once transaction.
  17309.  
  17310. ATPSndRequest completes when either the transaction is completed or the retry count
  17311. is exceeded.
  17312.  
  17313. Result codes    noErr          No error
  17314.                 reqFailed      Retry count exceeded
  17315.                 tooManyReqs    Too many concurrent requests
  17316.                 noDataArea     Too many outstanding ATP calls
  17317.  
  17318. FUNCTION ATPRequest (abRecord:  ABRecHandle;
  17319.                      async:  BOOLEAN) :  OSErr; [Not in ROM]
  17320.  
  17321. ABusRecord
  17322.   <--    abOpcode         {always tATPRequest}
  17323.   <--    abResult         {result code}
  17324.   -->    abUserReference  {for your use}
  17325.   -->    atpAddress       {destination socket address}
  17326.   -->    atpReqCount      {request size in bytes}
  17327.   -->    atpDataPtr       {pointer to buffer}
  17328.   <--    atpActCount      {number of bytes actually received}
  17329.   -->    atpUserData      {user bytes}
  17330.   -->    atpXO            {exactly-once flag}
  17331.   <--    atpEOM           {end-of-message flag}
  17332.   -->    atpTimeOut       {retry timeout interval in seconds}
  17333.   -->    atpRetries       {maximum number of retries}
  17334.   <--    atpRspUData      {user bytes received in transaction response}
  17335.   -->    atpRspBuf        {pointer to response message buffer}
  17336.   -->    atpRspSize       {size of response message buffer}
  17337.  
  17338. ATPRequest is functionally analogous to ATPSndRequest. It sends a request to another
  17339. socket, but doesn’t require the caller to set up and use the BDS data structure to
  17340. describe the response buffers. ATPAddress indicates the socket to which the request
  17341. should be sent. ATPDataPtr and atpReqCount specify the location and size of a buffer
  17342. that contains the request information to be sent. ATPUserData contains the user bytes
  17343. to be sent in the request’s ATP header. ATPTimeOut indicates the length of time that
  17344. ATPRequest should wait for a response before retransmitting the request. ATPRetries
  17345. indicates the maximum number of retries ATPRequest should attempt.
  17346.  
  17347. To use this call, you must have an area of contiguous buffer space that’s large
  17348. enough to receive all expected datagrams. The various datagrams will be assembled in
  17349. this buffer and returned to you as a complete message upon completion of the transaction.
  17350. The location and size of this buffer are passed in atpRspBuf and atpRspSize. Upon
  17351. completion of the call, the size of the received response message is returned in
  17352. atpActCount. The user bytes received in the ATP header of the first response packet
  17353. are returned in atpRspUData. ATPXO should be TRUE if you want the request to be part
  17354. of an exactly-once transaction.
  17355.  
  17356. Although you don’t provide a BDS, ATPRequest in fact creates one and calls the
  17357. .ATP driver (as in an ATPSndRequest call). For this reason, the abRecord fields
  17358. atpRspBDSPtr and atpNumBufs are used by ATPRequest; you should not expect these
  17359. fields to remain unaltered during or after the function’s execution.
  17360.  
  17361. For ATPRequest to receive and correctly deliver the response as a single message, the
  17362. responding end must, upon receiving the request (with an ATPGetRequest call), generate
  17363. the complete response as a message in a single buffer and then call ATPResponse.
  17364.  
  17365. Note:  The responding end could also use ATPSndRsp and ATPAddRsp provided
  17366.        that each response packet (except the last one) contains exactly 578
  17367.        ATP data bytes; the last packet in the response can contain less than
  17368.        578 ATP data bytes. Also, if this method is used, only the ATP user
  17369.        bytes of the first response packet will be delivered to the requester;
  17370.        any information in the user bytes of the remaining response packets
  17371.        will not be delivered.
  17372.  
  17373. ATPRequest completes when either the transaction is completed or the retry count is
  17374. exceeded.
  17375.  
  17376. Result codes    noErr          No error
  17377.                 reqFailed      Retry count exceeded
  17378.                 tooManyReqs    Too many concurrent requests
  17379.                 sktClosed      Socket closed by a cancel call
  17380.                 noDataArea     Too many outstanding ATP calls
  17381.  
  17382. FUNCTION ATPReqCancel (abRecord:  ABRecHandle;
  17383.                        async:  BOOLEAN) :  OSErr; [Not in ROM]
  17384.  
  17385. Given the handle to the ABusRecord of a previously made ATPSndRequest or ATPRequest
  17386. call, ATPReqCancel dequeues the ATPSndRequest or ATPRequest call, provided that the
  17387. call hasn’t already completed. ATPReqCancel returns noErr if the ATPSndRequest or
  17388. ATPRequest call is successfully removed from the queue. If it returns cbNotFound,
  17389. check the abResult field of abRecord to verify that the ATPSndRequest or ATPRequest
  17390. call has completed and determine its outcome.
  17391.  
  17392. Result codes    noErr         No error
  17393.                 cbNotFound    ATP control block not found
  17394.  
  17395. FUNCTION ATPGetRequest (abRecord:  ABRecHandle;
  17396.                         async:  BOOLEAN) :  OSErr; [Not in ROM]
  17397.  
  17398. ABusRecord
  17399.   <--    abOpcode         {always tATPGetRequest}
  17400.   <--    abResult         {result code}
  17401.   -->    abUserReference  {for your use}
  17402.   -->    atpSocket        {listening socket number}
  17403.   <--    atpAddress       {source socket address}
  17404.   -->    atpReqCount      {buffer size in bytes}
  17405.   -->    atpDataPtr       {pointer to buffer}
  17406.   <--    atpBitMap        {transaction bit map}
  17407.   <--    atpTransID       {transaction ID}
  17408.   <--    atpActCount      {number of bytes actually received}
  17409.   <--    atpUserData      {user bytes}
  17410.   <--    atpXO            {exactly-once flag}
  17411.  
  17412. ATPGetRequest sets up the mechanism to receive a request sent by either an ATPSndRequest
  17413. or an ATPRequest call. ATPSocket contains the socket number of the socket that should
  17414. listen for a request; this socket must already have been opened by calling ATPOpenSocket.
  17415. The address of the socket from which the request was sent is returned in atpAddress.
  17416. ATPDataPtr specifies a buffer to store the incoming request; atpReqCount indicates
  17417. the size of the buffer in bytes. The number of bytes actually received in the request
  17418. is returned in atpActCount. ATPUserData contains the user bytes from the ATP header.
  17419. The transaction bit map is returned in atpBitMap. The transaction ID is returned in
  17420. atpTransID. ATPXO will be TRUE if the request is part of an exactly-once transaction.
  17421.  
  17422. ATPGetRequest completes when a request is received. To cancel an asynchronous ATPGetRequest
  17423. call, you must call ATPCloseSocket, but this cancels all pending calls involving that
  17424. socket.
  17425.  
  17426. Result codes    noErr        No error
  17427.                 badATPSkt    Bad responding socket
  17428.                 sktClosed    Socket closed by a cancel call
  17429.  
  17430. FUNCTION ATPSndRsp (abRecord:  ABRecHandle;
  17431.                     async:  BOOLEAN) :  OSErr; [Not in ROM]
  17432.  
  17433. ABusRecord
  17434.   <--    abOpcode         {always tATPSdRsp}
  17435.   <--    abResult         {result code}
  17436.   -->    abUserReference  {for your use}
  17437.   -->    atpSocket        {responding socket number}
  17438.   -->    atpAddress       {destination socket address}
  17439.   -->    atpRspBDSPtr     {pointer to response BDS}
  17440.   -->    atpTransID       {transaction ID}
  17441.   -->    atpEOM           {end-of-message flag}
  17442.   -->    atpNumBufs       {number of response packets being sent}
  17443.   -->    atpBDSSize       {number of elements in response BDS}
  17444.  
  17445. ATPSndRsp sends a response to another socket. ATPSocket contains the socket number
  17446. from which the response should be sent and atpAddress contains the internet address
  17447. of the socket to which the response should be sent. ATPTransID must contain the
  17448. transaction ID. ATPEOM is TRUE if the response BDS contains the final packet in a
  17449. transaction composed of a group of packets and the number of packets in the response
  17450. is less than expected. ATPRspBDSPtr points to the buffer data structure containing
  17451. the responses to be sent. ATPBDSSize indicates the number of elements in the response
  17452. BDS, and must be in the range 1 to 8. ATPNumBufs indicates the number of response
  17453. packets being sent with this call, and must be in the range 0 to 8.
  17454.  
  17455. Note:  In some situations, you may want to send only part (or possibly none)
  17456.        of your response message back immediately. For instance, you might be
  17457.        requested to send back seven disk blocks, but have only enough internal
  17458.        memory to store one block. In this case, set atpBDSSize to 7 (total
  17459.        number of response packets), atpNumBufs to 0 (number of response
  17460.        packets currently being sent), and call ATPSndRsp. Then as you read
  17461.        in one block at a time, call ATPAddRsp until all seven response
  17462.        datagrams have been sent.
  17463.  
  17464. During exactly-once transactions, ATPSndRsp won’t complete until the release packet
  17465. is received or the release timer expires.
  17466.  
  17467. Result codes    noErr         No error
  17468.                 badATPSkt     Bad responding socket
  17469.                 noRelErr      No release received
  17470.                 sktClosed     Socket closed by a cancel call
  17471.                 noDataArea    Too many outstanding ATP calls
  17472.                 badBuffNum    Bad sequence number
  17473.  
  17474. FUNCTION ATPAddRsp (abRecord:  ABRecHandle) :  OSErr; [Not in ROM]
  17475.  
  17476. ABusRecord
  17477.   <--    abOpcode         {always tATPAddRsp}
  17478.   <--    abResult         {result code}
  17479.   -->    abUserReference  {for your use}
  17480.   -->    atpSocket        {responding socket number}
  17481.   -->    atpAddress       {destination socket address}
  17482.   -->    atpReqCount      {buffer size in bytes}
  17483.   -->    atpDataPtr       {pointer to buffer}
  17484.   -->    atpTransID       {transaction ID}
  17485.   -->    atpUserData      {user bytes}
  17486.   -->    atpEOM           {end-of-message flag}
  17487.   -->    atpNumRsp        {sequence number}
  17488.  
  17489. ATPAddRsp sends one additional response packet to a socket that has already been sent
  17490. the initial part of a response via ATPSndRsp. ATPSocket contains the socket number
  17491. from which the response should be sent and atpAddress contains the internet address
  17492. of the socket to which the response should be sent. ATPTransID must contain the
  17493. transaction ID. ATPDataPtr and atpReqCount specify the location and size of a buffer
  17494. that contains the information to send; atpNumRsp is the sequence number of the response.
  17495. ATPEOM is TRUE if this response datagram is the final packet in a transaction composed
  17496. of a group of packets. ATPUserData contains the user bytes to be sent in this response
  17497. datagram’s ATP header.
  17498.  
  17499. Note:  No BDS is needed with ATPAddRsp because all pertinent information
  17500.        is passed within the record.
  17501.  
  17502. Result codes    noErr         No error
  17503.                 badATPSkt     Bad responding socket
  17504.                 badBuffNum    Bad sequence number
  17505.                 noSendResp    ATPAddRsp issued before ATPSndRsp
  17506.                 noDataArea    Too many outstanding ATP calls
  17507.  
  17508. FUNCTION ATPResponse (abRecord:  ABRecHandle;
  17509.                       async:  BOOLEAN) :  OSErr; [Not in ROM]
  17510.  
  17511. ABusRecord
  17512.   <--    abOpcode         {always tATPResponse}
  17513.   <--    abResult         {result code}
  17514.   -->    abUserReference  {for your use}
  17515.   -->    atpSocket        {responding socket number}
  17516.   -->    atpAddress       {destination socket address}
  17517.   -->    atpTransID       {transaction ID)
  17518.   -->    atpRspUData      {user bytes sent in transaction response}
  17519.   -->    atpRspBuf        {pointer to response message buffer}
  17520.   -->    atpRspSize       {size of response message buffer}
  17521.  
  17522. ATPResponse is functionally analogous to ATPSndRsp. It sends a response to another
  17523. socket, but doesn’t require the caller to provide a BDS. ATPAddress must contain the
  17524. complete network address of the socket to which the response should be sent (taken
  17525. from the data provided by an ATPGetRequest call). ATPTransID must contain the transaction
  17526. ID. ATPSocket indicates the socket from which the response should be sent (the socket
  17527. on which the corresponding ATPGetRequest was issued). ATPRspBuf points to the buffer
  17528. containing the response message; the size of this buffer must be passed in atpRspSize.
  17529. The four user bytes to be sent in the ATP header of the first response packet are
  17530. passed in atpRspUData. The last packet of the transaction response is sent with the
  17531. EOM flag set.
  17532.  
  17533. Although you don’t provide a BDS, ATPResponse in fact creates one and calls the .ATP
  17534. driver (as in an ATPSndRsp call). For this reason, the abRecord fields atpRspBDSPtr
  17535. and atpNumBufs are used by ATPResponse; you should not expect these fields to remain
  17536. unaltered during or after the function’s execution.
  17537.  
  17538. During exactly-once transactions ATPResponse won’t complete until the release packet
  17539. is received or the release timer expires.
  17540.  
  17541. Warning:  The maximum permissible size of the response message is 4624 bytes.
  17542.  
  17543. Result codes    noErr         No error
  17544.                 badATPSkt     Bad responding socket
  17545.                 noRelErr      No release received
  17546.                 atpLenErr     Response too big
  17547.                 sktClosed     Socket closed by a cancel call
  17548.                 noDataArea    Too many outstanding ATP calls
  17549.  
  17550. FUNCTION ATPRspCancel (abRecord:  ABRecHandle;
  17551.                        async:  BOOLEAN) :  OSErr; [Not in ROM]
  17552.  
  17553. Given the handle to the ABusRecord of a previously made ATPSndRsp or ATPResponse
  17554. call, ATPRspCancel dequeues the ATPSndRsp or ATPResponse call, provided that the call
  17555. hasn’t already completed. ATPRspCancel returns noErr if the ATPSndRsp or ATPResponse
  17556. call is successfully removed from the queue. If it returns cbNotFound, check the
  17557. abResult field of abRecord to verify that the ATPSndRsp or ATPResponse call has
  17558. completed and determine its outcome.
  17559.  
  17560. Result codes    noErr         No error
  17561.                 cbNotFound    ATP control block not found
  17562.  
  17563. »Example
  17564.  
  17565. This example shows the requesting side of an ATP transaction that asks for a 512-byte
  17566. disk block from the responding end. The block number of the file is a byte and is
  17567. contained in myBuffer[0].
  17568.  
  17569. VAR
  17570.   myABRecord: ABRecHandle;
  17571.   myBDSPtr: BDSPtr;
  17572.   myBuffer: PACKED ARRAY [0..511] OF CHAR;
  17573.   errCode: INTEGER;
  17574.   async: BOOLEAN;
  17575.  
  17576. BEGIN
  17577.   errCode := ATPLoad;
  17578.   IF errCode <> noErr THEN
  17579.     WRITELN('Error in opening AppleTalk')
  17580.     {Maybe serial port B isn't available for use by AppleTalk}
  17581.   ELSE
  17582.     BEGIN
  17583.       {Prepare the BDS; allocate space for a one-element BDS}
  17584.       myBDSPtr := BDSPtr(NewPtr(SIZEOF(BDSElement)));
  17585.       WITH myBDSPtr^[0] DO
  17586.         BEGIN
  17587.           buffSize := 512; {size of our buffer used in reception}
  17588.           buffPtr := @myBuffer; {pointer to the buffer}
  17589.         END;
  17590.       {Prepare the ABusRecord}
  17591.       myBuffer[0] := CHR(1); {requesting disk block number 1}
  17592.       myABRecord := ABRecHandle(NewHandle(atpSize));
  17593.       WITH myABRecord^^ DO
  17594.         BEGIN
  17595.           atpAddress.aNet := 0;
  17596.           atpAddress.aNode := 30; {we probably got this from an NBP call}
  17597.           atpAddress.aSocket := 15; {socket to send request to}
  17598.           atpReqCount := 1; {size of request data field (disk block #)}
  17599.           atpDataPtr := @myBuffer; {ptr to request to be sent}
  17600.           atpRspBDSPtr := @myBDSPtr;
  17601.           atpUserData := 0; {for your use}
  17602.           atpXO := FALSE; {at-least-once service}
  17603.           atpTimeOut := 5; {5-second timeout}
  17604.           atpRetries := 3; {3 retries; request will be sent 4 times max}
  17605.           atpNumBufs := 1; {we're only expecting 1 block to be returned}
  17606.         END;
  17607.       async := FALSE;
  17608.       {Send the request and wait for the response}
  17609.       errCode := ATPSndRequest(myABRecord, async);
  17610.       IF errCode <> noErr THEN
  17611.         WRITELN('An error occurred in the ATPSndRequest call')
  17612.       ELSE
  17613.         BEGIN
  17614.           {The disk block requested is now in myBuffer. We can verify }
  17615.           { that atpNumRsp contains 1, meaning one response received.}
  17616.         . . .
  17617.         END;
  17618.     END;
  17619. END.
  17620.  
  17621. _______________________________________________________________________________
  17622.  
  17623. »Name-Binding Protocol
  17624.  
  17625. »Data Structures
  17626.  
  17627. NBP calls use the following fields:
  17628.  
  17629. nbpProto:
  17630.   (nbpEntityPtr:       EntityPtr;     {pointer to entity name}
  17631.    nbpBufPtr:          Ptr;           {pointer to buffer}
  17632.    nbpBufSize:         INTEGER;       {buffer size in bytes}
  17633.    nbpDataField:       INTEGER;       {number of addresses or socket number}
  17634.    nbpAddress:         AddrBlock;     {socket address}
  17635.    nbpRetransmitInfo:  RetransType);  {retransmission information}
  17636.  
  17637. When data is sent via NBP, nbpBufSize indicates the size of the data in bytes and
  17638. nbpBufPtr points to a buffer containing the data. When data is received via NBP,
  17639. nbpBufPtr points to a buffer in which the incoming data can be stored and nbpBufSize
  17640. indicates the size of the buffer in bytes. NBPAddress is used in some calls to give
  17641. the internet address of a named entity. The AddrBlock data type is described above
  17642. under “Datagram Delivery Protocol”.
  17643.  
  17644. NBPEntityPtr points to a variable of type EntityName, which has the following data
  17645. structure:
  17646.  
  17647. TYPE  EntityName = RECORD
  17648.                      objStr:   Str32;   {object}
  17649.                      typeStr:  Str32;   {type}
  17650.                      zoneStr:  Str32    {zone}
  17651.                    END;
  17652.  
  17653.       EntityPtr = ^EntityName;
  17654.       Str32 = STRING[32];
  17655.  
  17656. NBPRetransmitInfo contains information about the number of times a packet should be
  17657. transmitted and the interval between retransmissions:
  17658.  
  17659. TYPE  RetransType =  PACKED RECORD
  17660.                        retransInterval:  Byte;    {retransmit interval in }
  17661.                                                   { 8-tick units}
  17662.                        retransCount:     Byte     {total number of attempts}
  17663.                      END;
  17664.  
  17665. RetransCount contains the total number of times a packet should be transmitted,
  17666. including the first transmission. If retransCount is 0, the packet will be transmitted
  17667. a total of 255 times.
  17668.  
  17669. »Using NBP
  17670.  
  17671. On a Macintosh 128K, the AppleTalk Manager’s NBP code is read into the application
  17672. heap when any one of the NBP (Pascal) routines is called; you can call the NBPLoad
  17673. function yourself if you want to load the NBP code explicitly. When you’re finished
  17674. with the NBP code and want to reclaim the space it occupies, call NBPUnload. On a
  17675. Macintosh 512K or XL, the NBP code is read in when the .MPP driver is loaded.
  17676.  
  17677. Note:  When another application starts up, the application heap is
  17678.        reinitialized; on a Macintosh 128K, this means that the NBP
  17679.        code is lost (and must be reloaded by the next application).
  17680.  
  17681. When an entity wants to communicate via an AppleTalk network, it should call NBPRegister
  17682. to place its name and internet address in the names table. When an entity no longer
  17683. wants to communicate on the network, or is being shut down, it should call NBPRemove
  17684. to remove its entry from the names table.
  17685.  
  17686. To determine the address of an entity you know only by name, call NBPLookup, which
  17687. returns a list of all entities with the name you specify. Call NBPExtract to extract
  17688. entity names from the list.
  17689.  
  17690. If you already know the address of an entity, and want only to confirm that it still
  17691. exists, call NBPConfirm. NBPConfirm is more efficient than NBPLookup in terms of
  17692. network traffic.
  17693.  
  17694. »NBP Routines
  17695.  
  17696. FUNCTION NBPRegister (abRecord:  ABRecHandle;
  17697.                       async:  BOOLEAN) :  OSErr; [Not in ROM]
  17698.  
  17699. ABusRecord
  17700.   <--    abOpcode            {always tNBPRegister}
  17701.   <--    abResult            {result code}
  17702.   -->    abUserReference     {for your use}
  17703.   -->    nbpEntityPtr        {pointer to entity name}
  17704.   -->    nbpBufPtr           {pointer to buffer}
  17705.   -->    nbpBufSize          {buffer size in bytes}
  17706.   -->    nbpAddress.aSocket  {socket address}
  17707.   -->    nbpRetransmitInfo   {retransmission information}
  17708.  
  17709. NBPRegister adds the name and address of an entity to the node’s names table. NBPEntityPtr
  17710. points to a variable of type EntityName containing the entity’s name. If the name is
  17711. already registered, NBPRegister returns the result code nbpDuplicate. NBPAddress
  17712. indicates the socket for which the name should be registered. NBPBufPtr and nbpBufSize
  17713. specify the location and size of a buffer for NBP to use internally.
  17714.  
  17715. While the variable of type EntityName is declared as three 32-byte strings, only the
  17716. actual characters of the name are placed in the buffer pointed to by nbpBufPtr. For
  17717. this reason, nbpBufSize needs only to be equal to the actual length of the name, plus
  17718. an additional 12 bytes for use by NBP.
  17719.  
  17720. Warning:  This buffer must not be altered or released until the name is
  17721.           removed from the names table via an NBPRemove call. If you
  17722.           allocate the buffer through a NewHandle call, you must lock
  17723.           it as long as the name is registered.
  17724.  
  17725. Warning:  The zone field of the entity name must be set to the
  17726.           meta-character “*”.
  17727.  
  17728. Result codes    noErr           No error
  17729.                 nbpDuplicate    Duplicate name already exists
  17730.  
  17731. FUNCTION NBPLookup (abRecord:  ABRecHandle;
  17732.                     async:  BOOLEAN) :  OSErr; [Not in ROM]
  17733.  
  17734. ABusRecord
  17735.   <--    abOpcode           {always tNBPLookup}
  17736.   <--    abResult           {result code}
  17737.   -->    abUserReference    {for your use}
  17738.   -->    nbpEntityPtr       {pointer to entity name}
  17739.   -->    nbpBufPtr          {pointer to buffer}
  17740.   -->    nbpBufSize         {buffer size in bytes}
  17741.   <->    nbpDataField       {number of addresses received}
  17742.   -->    nbpRetransmitInfo  {retransmission information}
  17743.  
  17744. NBPLookup returns the addresses of all entities with a specified name. NBPEntityPtr
  17745. points to a variable of type EntityName containing the name of the entity whose
  17746. address should be returned. (Meta-characters are allowed in the entity name.) NBPBufPtr
  17747. and nbpBufSize contain the location and size of an area of memory in which the entity
  17748. names and their corresponding addresses should be returned. NBPDataField indicates
  17749. the maximum number of matching names to find addresses for; the actual number of
  17750. addresses found is returned in nbpDataField. NBPRetransmitInfo contains the retry
  17751. interval and the retry count.
  17752.  
  17753. When specifying nbpBufSize, for each NBP tuple expected, allow space for the actual
  17754. characters of the name, the address, and four bytes for use by NBP.
  17755.  
  17756. Result codes    noErr         No error
  17757.                 nbpBuffOvr    Buffer overflow
  17758.  
  17759. FUNCTION NBPExtract (theBuffer:  Ptr; numInBuf:  INTEGER; whichOne:  INTEGER;
  17760.                      VAR abEntity:  EntityName;
  17761.                      VAR address:  AddrBlock) :  OSErr; [Not in ROM]
  17762.  
  17763. NBPExtract returns one address from the list of addresses returned by NBPLookup.
  17764. TheBuffer and numInBuf indicate the location and number of tuples in the buffer.
  17765. WhichOne specifies which one of the tuples in the buffer should be returned in the
  17766. abEntity and address parameters.
  17767.  
  17768. Result codes    noErr         No error
  17769.                 extractErr    Can’t find tuple in buffer
  17770.  
  17771. FUNCTION NBPConfirm (abRecord:  ABRecHandle;
  17772.                      async:  BOOLEAN) :  OSErr; [Not in ROM]
  17773.  
  17774. ABusRecord
  17775.   <--    abOpcode           {always tNBPConfirm}
  17776.   <--    abResult           {result code}
  17777.   -->    abUserReference    {for your use}
  17778.   -->    nbpEntityPtr       {pointer to entity name}
  17779.   <--    nbpDataField       {socket number}
  17780.   -->    nbpAddress         {socket address}
  17781.   -->    nbpRetransmitInfo  {retransmission information}
  17782.  
  17783. NBPConfirm confirms that an entity known by name and address still exists (is still
  17784. entered in the names directory). NBPEntityPtr points to a variable of type EntityName
  17785. that contains the name to confirm, and nbpAddress specifies the address to be confirmed.
  17786. (No meta-characters are allowed in the entity name.) NBPRetransmitInfo contains the
  17787. retry interval and the retry count. The socket number of the entity is returned in
  17788. nbpDataField. NBPConfirm is more efficient than NBPLookup in terms of network traffic.
  17789.  
  17790. Result codes    noErr           No error
  17791.                 nbpConfDiff     Name confirmed for different socket
  17792.                 nbpNoConfirm    Name not confirmed
  17793.  
  17794. FUNCTION NBPRemove (abEntity:  EntityPtr) :  OSErr; [Not in ROM]
  17795.  
  17796. NBPRemove removes an entity name from the names table of the given entity’s node.
  17797.  
  17798. Result codes    noErr          No error
  17799.                 nbpNotFound    Name not found
  17800.  
  17801. FUNCTION NBPLoad :  OSErr; [Not in ROM]
  17802.  
  17803. On a Macintosh 128K, NBPLoad reads the NBP code from the system resource file into
  17804. the application heap. On a Macintosh 512K or XL, NBPLoad has no effect since the NBP
  17805. code should have already been loaded when the .MPP driver was opened. Normally you’ll
  17806. never need to call NBPLoad, because the AppleTalk Manager calls it when necessary.
  17807.  
  17808. Result codes    noErr    No error
  17809.  
  17810. FUNCTION NBPUnload :  OSErr; [Not in ROM]
  17811.  
  17812. On a Macintosh 128K, NBPUnload makes the NBP code purgeable; the space isn’t actually
  17813. released by the Memory Manager until necessary. On a Macintosh 512K or Macintosh XL,
  17814. NBPUnload has no effect.
  17815.  
  17816. Result codes    noErr    No error
  17817.  
  17818. »Example
  17819.  
  17820. This example of NBP registers our node as a print spooler, searches for any print
  17821. spoolers registered on the network, and then extracts the information for the first
  17822. one found.
  17823.  
  17824. CONST
  17825.   mySocket = 20;
  17826.  
  17827. VAR
  17828.   myABRecord: ABRecHandle;
  17829.   myEntity: EntityName;
  17830.   entityAddr: AddrBlock;
  17831.   nbpNamePtr: Ptr;
  17832.   myBuffer: PACKED ARRAY [0..999] OF CHAR;
  17833.   errCode: INTEGER;
  17834.   async: BOOLEAN;
  17835.  
  17836. BEGIN
  17837.   errCode := MPPOpen;
  17838.   IF errCode <> noErr THEN
  17839.     WRITELN('Error in opening AppleTalk')
  17840.     {Maybe serial port B isn't available for use by AppleTalk}
  17841.   ELSE
  17842.     BEGIN
  17843.       {Call Memory Manager to allocate ABusRecord}
  17844.       myABRecord := ABRecHandle(NewHandle(nbpSize));
  17845.       {Set up our entity name to register}
  17846.       WITH myEntity DO
  17847.         BEGIN
  17848.           objStr := 'Gene Station'; {we are called 'Gene Station' }
  17849.           typeStr := 'PrintSpooler'; { and are of type 'PrintSpooler'}
  17850.           zoneStr := '*';
  17851.           {Allocate data space for the entity name (used by NBP)}
  17852.           nbpNamePtr := NewPtr(LENGTH(objStr) + LENGTH(typeStr) +
  17853.                                LENGTH(zoneStr) + 12);
  17854.         END;
  17855.       {Set up the ABusRecord for the NBPRegister call}
  17856.       WITH myABRecord^^ DO
  17857.         BEGIN
  17858.           nbpEntityPtr := @myEntity;
  17859.           nbpBufPtr := nbpNamePtr; {buffer used by NBP internally}
  17860.           nbpBufSize := nbpNameBufSize;
  17861.           nbpAddress.aSocket := mySocket; {socket to register us on}
  17862.           nbpRetransmitInfo.retransInterval := 8; {retransmit every 64 }
  17863.           nbpRetransmitInfo.retransCount := 3; { ticks and try 3 times}
  17864.         END;
  17865.       async := FALSE;
  17866.       errCode := NBPRegister(myABRecord, async);
  17867.       IF errCode <> noErr THEN
  17868.         WRITELN('Error occurred in the NBPRegister call')
  17869.         {Maybe the name is already registered somewhere else on the }
  17870.         { network.}
  17871.       ELSE
  17872.         BEGIN
  17873.           {Now that we've registered our name, find others of type }
  17874.           { 'PrintSpooler'.}
  17875.           WITH myEntity DO
  17876.             BEGIN
  17877.               objStr := '='; {any one of type }
  17878.               typeStr := 'PrintSpooler'; { “PrintSpooler” }
  17879.               zoneStr := '*'; { in our zone}
  17880.             END;
  17881.           WITH myABRecord^^ DO
  17882.             BEGIN
  17883.               nbpEntityPtr := @myEntity;
  17884.               nbpBufPtr := @myBuffer; {buffer to place responses in}
  17885.               nbpBufSize := SIZEOF(myBuffer);
  17886.              {The field nbpDataField, before the NBPLookup call, represents an }
  17887.               { approximate number of responses. After the call, nbpDataField }
  17888.               { contains the actual number of responses received.}
  17889.               nbpDataField := 100; {we want about 100 responses back}
  17890.             END;
  17891.           errCode := NBPLookup(myABRecord, async); {make sync call}
  17892.           IF errCode <> noErr THEN
  17893.             WRITELN('An error occurred in the NBPLookup')
  17894.             {Did the buffer overflow?}
  17895.           ELSE
  17896.             BEGIN
  17897.               {Get the first reply}
  17898.               errCode := NBPExtract(@mybuffer, myABRecord^^.nbpDataField, 1,
  17899.                                     myEntity, entityAddr);
  17900.            {The socket address and name of the entity are returned here. If we }
  17901.              { want all of them, we'll have to loop for each one in the buffer.}
  17902.               IF errCode <> noErr THEN WRITELN('Error in NBPExtract');
  17903.               {Maybe the one we wanted wasn't in the buffer}
  17904.             END;
  17905.         END;
  17906.     END;
  17907. END.
  17908.  
  17909. _______________________________________________________________________________
  17910.  
  17911. »Miscellaneous Routines
  17912.  
  17913. FUNCTION GetNodeAddress (VAR myNode,myNet:  INTEGER) :  OSErr; [Not in ROM]
  17914.  
  17915. GetNodeAddress returns the current node ID and network number of the caller. If the
  17916. .MPP driver isn’t installed, it returns noMPPErr. If myNet contains 0, this means
  17917. that a bridge hasn’t yet been found.
  17918.  
  17919. Result codes    noErr       No error
  17920.                 noMPPErr    MPP driver not installed
  17921.  
  17922. FUNCTION IsMPPOpen :  BOOLEAN; [Not in ROM]
  17923.  
  17924. IsMPPOpen returns TRUE if the .MPP driver is loaded and running.
  17925.  
  17926. FUNCTION IsATPOpen :  BOOLEAN; [Not in ROM]
  17927.  
  17928. IsATPOpen returns TRUE if the .ATP driver is loaded and running.
  17929.  
  17930. _______________________________________________________________________________
  17931.  
  17932.  
  17933. æKY New…AppleTalk…Manager…Pascal…Interface
  17934. æC »NEW APPLETALK MANAGER PASCAL INTERFACE                   AppleTalkManager
  17935. _______________________________________________________________________________
  17936.  
  17937. In addition to the interface documented in the previous section, a new parameter
  17938. block–style interface to the AppleTalk Manager is now available for Pascal programmers.
  17939. This new interface, referred to as the preferred interface, is available in addition
  17940. to the Pascal interface described in the previous section, which is referred to as
  17941. the alternate interface.  All AppleTalk Manager calls, old and new, are supported by
  17942. the preferred interface.
  17943.  
  17944. The alternate interface has not been extended to support the new AppleTalk Manager
  17945. calls.  However, the alternate interface provides the only implementation of LAPRead
  17946. and DDPRead. These are higher-level calls not directly supported through the assembly-language
  17947. interface.  Developers will wish to use the alternate interface for these calls, and
  17948. also for compatibility with previous applications.  In all other cases, it is recommended
  17949. that the new preferred interface be used.
  17950.  
  17951. _______________________________________________________________________________
  17952.  
  17953. »Using Pascal
  17954.  
  17955. All AppleTalk Manager calls in the  preferred interface are essentially equivalent to
  17956. the corresponding assembly-language calls.  Their form is
  17957.  
  17958. FUNCTION MPPCall (pbPtr: Ptr; asyncFlag: BOOLEAN) : OSErr;
  17959.  
  17960. where pbPtr points to a device manager parameter block, and asyncFlag is TRUE if the
  17961. call is to be executed asynchronously.  Three parameter block types are provided by
  17962. the preferred interface (MPP, ATP, and XPP).  The MPP parameter block is shown below.
  17963.  The ATP parameter block is shown in the following section, and the XPP parameter
  17964. block is shown in the “Calling the .XPP Driver” section of this document. The field
  17965. names in these parameter blocks are the same as the parameter block offset names
  17966. defined in the assembly-language section (except as documented below).  The caller
  17967. fills in the parameter block with the fields as specified in that section and issues
  17968. the appropriate call.  The interface issues the actual device manager control call.
  17969.  
  17970. On asynchronous calls, the caller may pass a completion routine pointer in the parameter
  17971. block, at offset ioCompletion.  This routine will be executed upon completion of the
  17972. call.  It is executed at interrupt level and must not make any memory manager calls. 
  17973. If it uses application globals, it must ensure that register A5 is set up correctly;
  17974. for details see SetupA5 and RestoreA5 in the Operating System Utilities chapter.  If
  17975. no completion routine is desired, ioCompletion should be set to NIL.
  17976.  
  17977. Asynchronous calls return control to the caller with result code of noErr as soon as
  17978. they are queued to the driver.  This isn’t an indication of successful completion. 
  17979. To determine when the call is actually completed, if you don’t want to use a completion
  17980. routine, you can poll the ioResult field; this field is set to 1 when the call is
  17981. made, and receives the actual result code upon completion.
  17982.  
  17983. Refer to the appropriate sections of this chapter for the parameter blocks used by
  17984. each MPP and ATP call.  As different MPP and ATP calls take different arguments in
  17985. their parameter block, two Pascal variant records have been defined to account for
  17986. all the different cases.  These parameter blocks are shown in the sections that
  17987. follow.  The first four fields (which are the same for all calls) are automatically
  17988. filled in by the device manager.  The csCode and ioRefnum fields are automatically
  17989. filled in by the interface, depending on which call is being made, except in XPP
  17990. where the caller must fill in the ioRefnum.  The ioVRefnum field is unused.
  17991.  
  17992. There are two fields that at the assembly-language level have more than one name. 
  17993. These two fields have been given only one name in the preferred interface.  These are
  17994. entityPtr and ntqelPtr, which are both referred to as entityPtr, and atpSocket and
  17995. currBitmap, which are both referred to as atpSocket. These are the only exceptions to
  17996. the naming convention.
  17997.  
  17998. »MPP Parameter Block
  17999.  
  18000. MPPParamBlock = PACKED RECORD
  18001.        qLink:          QElemPtr;     {next queue entry}
  18002.        qType:          INTEGER;      {queue type}
  18003.        ioTrap:         INTEGER;      {routine trap}
  18004.        ioCmdAddr:      Ptr;          {routine address}
  18005.        ioCompletion:   ProcPtr;      {completion routine}
  18006.        ioResult:       OSErr;        {result code}
  18007.        ioNamePtr:      StringPtr;    {command result (ATP user bytes) [long]}
  18008.        ioVRefNum:      INTEGER;      {volume reference or drive number}
  18009.        ioRefNum:       INTEGER;      {driver reference number}
  18010.        csCode:         INTEGER;      {call command code AUTOMATICALLY SET}
  18011.  
  18012.        CASE MPPParmType OF
  18013.        LAPWriteParm:
  18014.                     (filler0:INTEGER;
  18015.                     wdsPointer:Ptr);    {->Write Data Structure}
  18016.        AttachPHParm,DetachPHParm:
  18017.                     (protType:Byte;     {ALAP Protocol Type}
  18018.                     filler1:Byte;
  18019.                     handler:Ptr);       {->protocol handler routine}
  18020.        OpenSktParm,CloseSktParm,WriteDDPParm:
  18021.                     (socket:Byte;       {socket number}
  18022.                     checksumFlag:Byte;  {checksum flag}
  18023.                     listener:Ptr);      {->socket listener routine}
  18024.        RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
  18025.                     (interval:Byte;     {retry interval}
  18026.                     count:Byte;         {retry count}
  18027.                     entityPtr:Ptr;      {->names table element or }
  18028.                                         { ->entity name}
  18029.                     CASE MPPParmType OF
  18030.                     RegisterNameParm:
  18031.                              (verifyFlag:Byte;     {set if verify needed}
  18032.                               filler3:Byte);
  18033.                     LookupNameParm:
  18034.                                     (retBuffPtr:Ptr;       {->return buffer}
  18035.                                     retBuffSize:INTEGER;   {return buffer size}
  18036.                                     maxToGet:INTEGER;      {matches to get}
  18037.                                     numGotten:INTEGER);    {matched gotten}
  18038.                     ConfirmNameParm:
  18039.                                     (confirmAddr:AddrBlock; {->entity}
  18040.                                     newSocket:Byte;         {socket number}
  18041.                                     filler4:Byte));
  18042.  
  18043.        SetSelfSendParm:
  18044.                     (newSelfFlag:Byte;  {self-send toggle flag}
  18045.                     oldSelfFlag:Byte);  {previous self-send state}
  18046.        KillNBPParm:
  18047.                     (nKillQEl:Ptr);     {ptr to Q element to cancel}
  18048.      END;
  18049.  
  18050. »ATP Parameter Block
  18051.  
  18052. ATPParamBlock = PACKED RECORD
  18053.          qLink:            QElemPtr;    {next queue entry}
  18054.          qType:            INTEGER;     {queue type}
  18055.          ioTrap:           INTEGER;     {routine trap}
  18056.          ioCmdAddr:        Ptr;         {routine address}
  18057.          ioCompletion:     ProcPtr;     {completion routine}
  18058.          ioResult:         OSErr;       {result code}
  18059.          userData:         LONGINT;     {ATP user bytes [long]}
  18060.          reqTID:           INTEGER;     {request transaction ID}
  18061.          ioRefNum:         INTEGER;     {driver reference number
  18062.          csCode:           INTEGER;     {Call command code }
  18063.                                         { AUTOMATICALLY SET}
  18064.          atpSocket:        Byte;        {currBitMap or socket number}
  18065.          atpFlags:         Byte;        {control information}
  18066.          addrBlock:        AddrBlock;   {source/dest. socket address}
  18067.          reqLength:        INTEGER;     {request/response length}
  18068.          reqPointer:       Ptr;         {-> request/response data}
  18069.          bdsPointer:       Ptr;         {-> response BDS}
  18070.          CASE MPPParmType OF
  18071.                 SendRequestParm,NSendRequestParm:
  18072.                     (numOfBuffs:Byte;   {numOfBuffs}
  18073.                     timeOutVal:Byte;    {timeout interval}
  18074.                     numOfResps:Byte;    {number responses actually received}
  18075.                     retryCount:Byte;    {number of retries}
  18076.                     intBuff:INTEGER);   {used internally for NSendRequest}
  18077.                 SendResponseParm:
  18078.                     (filler0:Byte;      {number of responses being sent}
  18079.                     bdsSize:Byte;       {number of BDS elements}
  18080.                     transID:INTEGER);   {transaction ID}
  18081.                 GetRequestParm:
  18082.                     (bitMap:Byte;       {bit map}
  18083.                     filler1:Byte);
  18084.                 AddResponseParm:
  18085.                     (rspNum:Byte;       {sequence number}
  18086.                     filler2:Byte);
  18087.                 KillSendReqParm,KillGetReqParm:
  18088.                     (aKillQEl:Ptr);     {ptr to Q element to cancel}
  18089.          END;
  18090.  
  18091. The following table is a complete list of all the parameter block calls provided by
  18092. the preferred interface.
  18093.  
  18094. AppleTalk
  18095. Manager
  18096. Routine       Preferred Interface Call
  18097.  
  18098. AttachPH      Function PAttachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18099. DetachPH      Function PDetachPH (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18100. WriteLAP      Function PWriteLAP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18101. OpenSkt       Function POpenSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18102. CloseSkt      Function PCloseSkt (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18103. WriteDDP      Function PWriteDDP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18104. RegisterName  Function PRegisterName (thePBptr: MPPPBPtr;
  18105.                                       async: BOOLEAN) : OSErr;
  18106. LookupName    Function PLookupName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18107. ConfirmName   Function PConfirmName (thePBptr: MPPPBPtr;
  18108.                                      async: BOOLEAN) : OSErr;
  18109. RemoveName    Function PRemoveName (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18110. OpenATPSkt    Function POpenATPSkt (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18111. CloseATPSkt   Function PCloseATPSkt (thePBptr: ATPPBPtr;
  18112.                                      async: BOOLEAN) : OSErr;
  18113. SendRequest   Function PSendRequest (thePBptr: ATPPBPtr;
  18114.                                      async: BOOLEAN) : OSErr;
  18115. GetRequest    Function PGetRequest (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18116. SendResponse  Function PSendResponse (thePBptr: ATPPBPtr;
  18117.                                       async: BOOLEAN) : OSErr;
  18118. AddResponse   Function PAddResponse(thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18119. ReltCB        Function PRelTCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18120. RelRspCB      Function PRelRspCB (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18121. SetSelfSend   Function PSetSelfSend (thePBptr: MPPPBPtr;
  18122.                                      async: BOOLEAN) : OSErr;
  18123. NSendRequest  Function PNSendRequest (thePBptr: ATPPBPtr;
  18124.                                       async: BOOLEAN) : OSErr;
  18125. KillSendReq   Function PKillSendReq (thePBptr: ATPPBPtr;
  18126.                                      async: BOOLEAN) : OSErr;
  18127. KillGetReq    Function PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18128. KillNBP       Function PKillNBP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18129.  
  18130. _______________________________________________________________________________
  18131.  
  18132. »Building Data Structures
  18133.  
  18134. Because it is difficult for Pascal to deal with certain assembly-language structures,
  18135. the preferred interface provides a number of routines for building these structures. 
  18136. These routines are summarized below.
  18137.  
  18138. PROCEDURE BuildLAPwds (wdsPtr,dataPtr: Ptr;
  18139.                        destHost,protoType,frameLen: INTEGER);
  18140.  
  18141. This routine builds a single-frame write data structure LAP WDS for use with the
  18142. PWriteLAP call.  Given a buffer of length frameLen pointed to by dataPtr, it fills in
  18143. the WDS pointed to by wdsPtr and sets the destination node and protocol type as
  18144. indicated by destHost and protoType, respectively.  The WDS indicated must contain at
  18145. least two elements.
  18146.  
  18147. PROCEDURE BuildDDPwds  (wdsPtr,headerPtr,dataPtr: Ptr; destAddress: AddrBlock;
  18148.                         DDPType : INTEGER; dataLen: INTEGER);
  18149.  
  18150. This routine builds a single-frame write data structure  DDP WDS, for use with the
  18151. PWriteDDP call.  Given a header buffer of at least 17 bytes pointed to by headerPtr
  18152. and a data buffer of length dataLen pointed to by dataPtr, it fills in the WDS pointed
  18153. to by wdsPtr, and sets the destination address and protocol type as indicated by
  18154. destaddress and DDPtype, respectively.  The WDS indicated must contain at least 3
  18155. elements.
  18156.  
  18157. PROCEDURE NBPSetEntity (buffer: Ptr; nbpObject,nbpType,nbpZone: Str32);
  18158.  
  18159. This routine builds an NBP entity structure, for use with the PLookupNBP and PConfirmName
  18160. calls.  Given a buffer of at least the size of the EntityName data structure (99
  18161. bytes) pointed to by buffer, this routine sets the indicated object, type, and zone
  18162. in that buffer.
  18163.  
  18164. PROCEDURE NBPSetNTE (ntePtr: Ptr; nbpObject,nbpType,nbpZone: Str32;
  18165.                      Socket: INTEGER);
  18166.  
  18167. This routine builds an NBP names table entry, for use with the PRegisterName call. 
  18168. Given a names table entry of at least the size of the EntityName data structure plus
  18169. nine bytes (108 bytes) pointed to by ntePtr, this routine sets the indicated object,
  18170. type, zone, and socket in that names table entry.
  18171.  
  18172. FUNCTION NBPExtract (theBuffer: Ptr; numInBuf: INTEGER; whichOne: INTEGER; VAR abEntity:
  18173. EntityName; VAR address: AddrBlock) : OSErr;
  18174.  
  18175. This routine is provided in the alternate interface, but can be used as provided for
  18176. extracting NBP entity names from a look-up response buffer.
  18177.  
  18178. FUNCTION GetBridgeAddress: INTEGER;
  18179.  
  18180. This routine returns the current address of a bridge in the low byte, or zero if
  18181. there is none.
  18182.  
  18183. FUNCTION BuildBDS (buffPtr,bdsPtr: Ptr; buffSize: INTEGER) : INTEGER;
  18184.  
  18185. This routine builds a BDS, for use with the ATP calls.  Given a data buffer of length
  18186. buffSize pointed to by buffPtr, it fills in the BDS pointed to by bdsPtr.  The buffer
  18187. will be broken up into pieces of maximum size (578 bytes).  The user bytes in the BDS
  18188. are not modified by this routine.  This routine is provided only as a convenience;
  18189. generally the caller will be able to build the BDS completely from Pascal without
  18190. it.
  18191.  
  18192. _______________________________________________________________________________
  18193.  
  18194.  
  18195. æKY Picking…a…Node…Address…in…the…Server…Range
  18196. æC »PICKING A NODE ADDRESS IN THE SERVER RANGE               AppleTalkManager
  18197. _______________________________________________________________________________
  18198.  
  18199. Normally upon opening, the node number picked by the AppleTalk manager will be in the
  18200. node number range ($01–$7F).  It is possible to indicate that a node number in the
  18201. server range ($80–$FE) is desired.  Picking a number in the server range is a more
  18202. time-consuming but more thorough process, and it’s required for server nodes because
  18203. it greatly decreases the possibility of a node number conflict.
  18204.  
  18205. To open AppleTalk with a server node number, an extended open call is used.  An
  18206. extended open call is indicated by having the immediate bit set in the Open trap
  18207. itself.  In the extended open call, the high bit (bit 31) of the extension longword
  18208. field (ioMix) indicates whether a server or workstation node number should be picked.
  18209.  Set this bit to 1 to request a server node number.  The rest of this field should be
  18210. zero, as should all other unused fields in the queue element.   A server node number
  18211. can only be requested on the first Open call to the .MPP driver.
  18212.  
  18213. _______________________________________________________________________________
  18214.  
  18215.  
  18216. æKY Sending…Packets…to…One’s…Own…Node
  18217. æC »SENDING PACKETS TO ONE’S OWN NODE                        AppleTalkManager
  18218. _______________________________________________________________________________
  18219.  
  18220. Upon opening, the ability to send a packet to one’s own node (intranode delivery) is
  18221. disabled.  This feature of the AppleTalk Manager can be manipulated through the
  18222. SetSelfSend function.  Once enabled, it is possible, at all levels, to send packets
  18223. to entities within one’s own node.  An example of where this might be desirable is an
  18224. application sending data to a print spooler that is actually running in the background
  18225. on the same node.
  18226.  
  18227. Enabling (or disabling) this feature affects the entire node and should be performed
  18228. with care.  For instance, a desk accessory may not expect to receive names from
  18229. within its own node as a response to an NBP look-up;  enabling this feature from an
  18230. application could break the desk accessory.  All future programs should be written
  18231. with this feature in mind.
  18232.  
  18233. FUNCTION PSetSelfSend (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
  18234.  
  18235. Parameter Block
  18236.   -->    26    csCode         word    Always PSetSelfSend
  18237.   -->    28    newSelfFlag    byte    New SelfSend flag
  18238.   <--    29    oldSelfFlag    byte    Old SelfSend flag
  18239.  
  18240. PSetSelfSend enables or disables the intranode delivery feature of the AppleTalk
  18241. Manager.  If newSelfFlag is nonzero, the feature will be enabled; otherwise it will
  18242. be disabled.  The previous value of the flag will be returned in oldSelfFlag.
  18243.  
  18244. Result Codes    noErr        No error
  18245.  
  18246. _______________________________________________________________________________
  18247.  
  18248.  
  18249. æKY ATP…Driver…Changes
  18250. æC »ATP DRIVER CHANGES                                       AppleTalkManager
  18251. _______________________________________________________________________________
  18252.  
  18253. Changes to the ATP driver include the ability to send an ATP request through a specific
  18254. socket rather than having ATP open a new socket, a new call to abort outstanding
  18255. SendRequest calls, and a new call to abort specific outstanding GetRequest calls.
  18256.  
  18257. _______________________________________________________________________________
  18258.  
  18259. »Sending an ATP Request Through a Specified Socket
  18260.  
  18261. ATP requests can now be sent through client-specified sockets.  ATP previously would
  18262. open a dynamic socket, send the request through it, and close the socket when the
  18263. request was completed.  The client can now choose to send a request through an already-opened
  18264. socket; this also allows more than one request to be sent per socket.   A new call,
  18265. PNSendRequest, has been added for this purpose.  The function of the old SendRequest
  18266. call itself remains unchanged.
  18267.  
  18268. FUNCTION PNSendRequest (thePBptr: ATPBPtr; async: BOOLEAN) : OSErr;
  18269.  
  18270. Parameter block
  18271.   -->    18    userData     longword  User bytes
  18272.   <--    22    reqTID       word      Transaction ID used in request
  18273.   -->    26    csCode       word      Always sendRequest
  18274.   <->    28    atpSocket    byte      Socket to send request on
  18275.                                        or current bitmap
  18276.   <->    29    atpFlags     byte      Control information
  18277.   -->    30    addrBlock    longword  Destination socket address
  18278.   -->    34    reqLength    word      Request size in bytes
  18279.   -->    36    reqPointer   pointer   Pointer to request data
  18280.   -->    40    bdsPointer   pointer   Pointer to response BDS
  18281.   -->    44    numOfBuffs   byte      Number of responses expected
  18282.   -->    45    timeOutVal   byte      Timeout interval
  18283.   <--    46    numOf Resps  byte      Number of responses received
  18284.   <->    47    retryCount   byte      Number of retries
  18285.   <--    48    intBuff      word      Used internally
  18286.  
  18287. The PNSendRequest call is functionally equivalent to the SendRequest call, however
  18288. PNSendRequest allows you to specify, in the atpSocket field, the socket through which
  18289. the request is to be sent.  This socket must have been previously opened through an
  18290. OpenATPSkt request (otherwise a badATPSkt error will be returned).  Note that PNSendRequest
  18291. requires two additional bytes of memory at the end of the parameter block, immediately
  18292. following the retryCount.  These bytes are for the internal use of the AppleTalk
  18293. Manager and should not be modified while the PNSendRequest call is active.
  18294.  
  18295. There is a machine-dependent limit as to the number of concurrent PNSendRequests that
  18296. can be active on a given socket.  If this limit is exceeded, the error tooManyReqs is
  18297. returned.
  18298.  
  18299. One additional difference between SendRequest and PNSendRequest is that a PNSendRequest
  18300. can only be aborted by a PKillSendReq call (see below), whereas a SendRequest can be
  18301. aborted by either a RelTCB or KillSendReq call.
  18302.  
  18303. Result Codes    noErr          No error
  18304.                 reqFailed      Retry count exceeded
  18305.                 tooManyReqs    Too many concurrent requests
  18306.                 noDataArea     Too many outstanding ATP calls
  18307.                 reqAborted     Request cancelled by user
  18308.  
  18309. _______________________________________________________________________________
  18310.  
  18311. »Aborting ATP SendRequests
  18312.  
  18313. The  RelTCB call is still supported, but only for aborting SendRequests.  To abort
  18314. PNSendRequests, a new call, PKillSendReq, has been added.  This call will abort both
  18315. SendRequests and PNSendRequests.  PKillSendReq’s only argument is the queue element
  18316. pointer of the request to be aborted.  The queue element pointer is passed at the
  18317. offset of the PKillSendReq queue element specified by aKillQE1.
  18318.  
  18319. FUNCTION PKillSendReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18320.  
  18321. Parameter block
  18322.   -->    26    csCode    word     Always PKillSendReq
  18323.   -->    44    aKillQEl  pointer  Pointer to queue element
  18324.  
  18325. PKillSendReq is functionally equivalent to RelTCB, except that it takes different
  18326. arguments and will abort both SendRequests and PNSendRequests.  To abort one of these
  18327. calls, place a pointer to the queue element of the call to abort in aKillQEl and
  18328. issue the PKillSendReq call.
  18329.  
  18330. Result Codes    noErr          No error
  18331.                 cbNotFound     aKillQEl does not point to a SendReq
  18332.                                or NSendReq queue element
  18333.  
  18334. _______________________________________________________________________________
  18335.  
  18336. »Aborting ATP GetRequests
  18337.  
  18338. ATP GetRequests can now be aborted through the PKillGetReq call.  This call looks and
  18339. works just like the PKillSendReq call, and is used to abort a specific GetRequest
  18340. call.  Previously it was necessary to close the socket  to abort all GetRequest calls
  18341. on the socket.
  18342.  
  18343. FUNCTION PKillGetReq (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18344.  
  18345. Parameter block
  18346.   -->    26    csCode    word     Always PKillGetReq
  18347.   -->    44    aKillQEl  pointer  Pointer to queue element
  18348.  
  18349. PKillGetReq will abort a specific outstanding GetRequest call (as opposed to closing
  18350. the socket, which aborts all outstanding GetRequests on that socket).  The call will
  18351. be completed with a reqAborted error.  To abort a GetRequest, place a pointer to the
  18352. queue element of the call to abort in aKillQEl and issue the PKillGetReq call.
  18353.  
  18354. Result Codes    noErr         No error
  18355.                 cbNotFound    aKillQEl does not point to a GetReq
  18356.                               queue element
  18357.  
  18358. _______________________________________________________________________________
  18359.  
  18360.  
  18361. æKY Name…Binding…Protocol…Changes
  18362. æC »NAME BINDING PROTOCOL CHANGES                            AppleTalkManager
  18363. _______________________________________________________________________________
  18364.  
  18365. Changes to the Name Binding Protocol include supporting multiple concurrent requests
  18366. and a means for aborting an active request.
  18367.  
  18368. »Multiple Concurrent NBP Requests
  18369.  
  18370. NBP now supports multiple concurrent active requests.  Specifically, a number of
  18371. LookupNames, RegisterNames and ConfirmNames can all be active concurrently.  The
  18372. maximum number of  concurrent requests is machine dependent; if it is exceeded the
  18373. error tooManyReqs will be returned.  Active requests can be aborted by the PKillNBP
  18374. call.
  18375.  
  18376. »KillNBP function
  18377.  
  18378. FUNCTION PKillNBP (thePBptr: ATPPBPtr; async: BOOLEAN) : OSErr;
  18379.  
  18380. •••Refer to Technical Note #199:•••
  18381.  
  18382. Parameter block
  18383.   -->    26    csCode    word     Always PKillNBP
  18384.   -->    28    aKillQEl  pointer  Pointer to queue element
  18385.  
  18386. PKillNBP is used to abort an outstanding LookupName, RegisterName or ConfirmName
  18387. request.  To abort one of these calls, place a pointer to the queue element of the
  18388. call to abort in a KillQEl and issue the PKillNBP call.  The call will be completed
  18389. with a ReqAborted error.
  18390.  
  18391. Result Codes    noErr          No error
  18392.                 cbNotFound     aKillQEl does not point to a valid
  18393.                                NBP queue element
  18394.  
  18395. _______________________________________________________________________________
  18396.  
  18397.  
  18398. æKY Variable…Resources
  18399. æC »VARIABLE RESOURCES                                       AppleTalkManager
  18400. _______________________________________________________________________________
  18401.  
  18402. The table below lists machine-dependent resources for the different Macintosh system
  18403. configurations.  The RAM-based resources are available through the AppleShare Server.
  18404.  
  18405. Resource    Macintosh Plus    RAM-Based    Macintosh SE    Macintosh II
  18406.  
  18407. Protocol
  18408. Handlers           4             8              8               8
  18409.  
  18410. Statically
  18411. Assigned
  18412. Sockets           14*           12             12              14
  18413.  
  18414. Concurrent
  18415. ATP SendRequests   6            12             12              12
  18416.  
  18417. ATP Sockets        6            32             32             126
  18418.  
  18419. Concurrent
  18420. ATP Responses      8            16             16              32
  18421.  
  18422. Concurrent
  18423. NBP Requests       1             6              6              10
  18424.  
  18425. Concurrent
  18426. ASP Sessions      N/A            5             10              20
  18427.  
  18428. Concurrent
  18429. ATP NSendRequests
  18430. Per Socket **     N/A            9             14              62
  18431.  
  18432. * Includes dynamic sockets
  18433. **  Determined dynamically at runtime based on CPU speed.
  18434. N/A : Not Applicable
  18435.  
  18436. _______________________________________________________________________________
  18437.  
  18438.  
  18439. æKY Calling…the…AppleTalk…Manager…from…Assembly…Language
  18440. æC »CALLING THE APPLETALK MANAGER FROM ASSEMBLY LANGUAGE      AppleTalkManager
  18441. _______________________________________________________________________________
  18442.  
  18443. This section discusses how to use the AppleTalk Manager from assembly language.
  18444. Equivalent Pascal information is given in the preceding section.
  18445.  
  18446. All routines make Device Manager Control calls. The description of each routine
  18447. includes a list of the fields needed. Some of these fields are part of the parameter
  18448. block described in the Device Manager chapter; additional fields are provided for the
  18449. AppleTalk Manager.
  18450.  
  18451. The number next to each field name indicates the byte offset of the field from the
  18452. start of the parameter block pointed to by A0. An arrow next to each parameter name
  18453. indicates whether it’s an input, output, or input/output parameter:
  18454.  
  18455. Arrow    Meaning
  18456.   -->    Parameter is passed to the routine
  18457.   <--    Parameter is returned by the routine
  18458.   <->    Parameter is passed to and returned by the routine
  18459.  
  18460. All Device Manager Control calls return an integer result code of type OSErr in the
  18461. ioResult field. Each routine description lists all of the applicable result codes
  18462. generated by the AppleTalk Manager, along with a short description of what the result
  18463. code means. Lengthier explanations of all the result codes can be found in the summary
  18464. at the end of this chapter. Result codes from other parts of the Operating System may
  18465. also be returned. (See Appendix A for a list of all result codes.)
  18466.  
  18467. _______________________________________________________________________________
  18468.  
  18469. »Opening AppleTalk
  18470.  
  18471. •••Refer to Technical Note #224:•••
  18472.  
  18473. Two tests are made at system startup to determine whether the .MPP driver should be
  18474. opened at that time. If port B is already in use, or isn’t configured for AppleTalk,
  18475. .MPP isn’t opened until explicitly requested by an application; otherwise it’s opened
  18476. at system startup.
  18477.  
  18478. It’s the application’s responsibility to test the availability of port B before
  18479. opening AppleTalk. Assembly-language programmers can use the Pascal calls MPPOpen and
  18480. ATPLoad to open the .MPP and .ATP drivers.
  18481.  
  18482. The global variable SPConfig is used for configuring the serial ports; it’s copied
  18483. from a byte in parameter RAM (which is discussed in the Operating System Utilities
  18484. chapter). The low-order four bits of this variable contain the current configuration
  18485. of port B. The following use types are provided as global constants for testing or
  18486. setting the configuration of port B:
  18487.  
  18488.   useFree     .EQU    0    ;unconfigured
  18489.   useATalk    .EQU    1    ;configured for AppleTalk
  18490.   useAsync    .EQU    2    ;configured for the Serial Driver
  18491.  
  18492. The application shouldn’t attempt to open AppleTalk unless SPConfig is equal to
  18493. either useFree or useATalk.
  18494.  
  18495. A second test involves the global variable PortBUse; the low-order four bits of this
  18496. byte are used to monitor the current use of port B. If PortBUse is negative, the
  18497. program is free to open AppleTalk. If PortBUse is positive, the program should test
  18498. to see whether port B is already being used by AppleTalk; if it is, the low-order
  18499. four bits of PortBUse will be equal to the use type useATalk.
  18500.  
  18501. The .MPP driver sets PortBUse to the correct value (useATalk) when it’s opened and
  18502. resets it to $FF when it’s closed. Bits 4-6 of this byte are used for driver-specific
  18503. information; ATP uses bit 4 to indicate whether it’s currently opened:
  18504.  
  18505. atpLoadedBit    .EQU    4    ;set if ATP is opened
  18506.  
  18507. »Example
  18508.  
  18509. The following code illustrates the use of the SPConfig and PortBUse variables.
  18510.  
  18511.           MOVE      #-<atpUnitNum+1>,atpRefNum(A0)  ;save known ATP refNum in
  18512.                                                     ; case ATP not opened
  18513. OpenAbus  SUB       #ioQElSize,SP     ;allocate queue entry
  18514.           MOVE.L    SP,A0             ;A0 -> queue entry
  18515.           CLR.B     ioPermssn(A0)     ;make sure permission's clear
  18516.           MOVE.B    PortBUse,D1       ;is port B in use?
  18517.           BPL.S     @10               ;if so, make sure by AppleTalk
  18518.           MOVEQ     #portNotCf,D0     ;assume port not configured for AppleTalk
  18519.           MOVE.B    SPConfig,D1       ;get configuration data
  18520.           AND.B     #$0F,D1           ;mask it to low 4 bits
  18521.           SUBQ.B    #useATalk,D1      ;unconfigured or configured for AppleTalk
  18522.           BGT.S     @30               ;if not, return error
  18523.           LEA       mppName,A1        ;A1 = address of driver name
  18524.           MOVE.L    A1,ioFileName(A0) ;set in queue entry
  18525.           _Open                       ;open MPP
  18526.           BNE.S     @30               ;return error, if it can't load it
  18527.           BRA.S     @20               ;otherwise, go check ATP
  18528. @10       MOVEQ     #portInUse,D0     ;assume port in use error
  18529.           AND.B     #$0F,D1           ;clear all but use bits
  18530.           SUBQ.B    #useATalk,D1      ;is AppleTalk using it?
  18531.           BNE.S     @30               ;if not, then error
  18532. @20       MOVEQ     #0,D0             ;assume no error
  18533.           BTST      #atpLoadedBit,PortBUse    ;ATP already open?
  18534.           BNE.S     @30               ;just return if so
  18535.           LEA       atpName,A1        ;A1 = address of driver name
  18536.           MOVE.L    A1,ioFileName(A0) ;set in queue entry
  18537.           _Open                       ;open ATP
  18538. @30       ADD       #ioQElSize,SP     ;deallocate queue entry
  18539.           RTS                         ;and return
  18540. mppName   .BYTE     4                 ;length of .MPP driver name
  18541.           .ASCII    '.MPP'            ;name of .MPP driver
  18542. atpName   .BYTE     4                 ;length of .ATP driver name
  18543.           .ASCII    '.ATP'            ;name of .ATP driver
  18544.  
  18545. _______________________________________________________________________________
  18546.  
  18547. »AppleTalk Link Access Protocol
  18548.  
  18549. »Data Structures
  18550.  
  18551. An ALAP frame is composed of a three-byte header, up to 600 bytes of data, and a
  18552. two-byte frame check sequence (Figure 6). You can use the following global constants
  18553. to access the contents of an ALAP header:
  18554.  
  18555.   lapDstAdr  .EQU    0    ;destination node ID
  18556.   lapSrcAdr  .EQU    1    ;source node ID
  18557.   lapType    .EQU    2    ;ALAP protocol type
  18558.   lapHdSz    .EQU    3    ;ALAP header size
  18559.  
  18560. •••Refer to Figure 6.•••
  18561.  
  18562. Figure 6–ALAP Frame
  18563.  
  18564. Two of the protocol handlers in every node are used by DDP. These protocol handlers
  18565. service frames with ALAP protocol types equal to the following global constants:
  18566.  
  18567.   shortDDP   .EQU    1    ;short DDP header
  18568.   longDDP    .EQU    2    ;long DDP header
  18569.  
  18570. When you call ALAP to send a frame, you pass it information about the frame in a
  18571. write data structure, which has the format shown in Figure 7.
  18572.  
  18573. •••Refer to Figure 7.•••
  18574.  
  18575. Figure 7–Write Data Structure for ALAP
  18576.  
  18577. If you specify a destination node ID of 255, the frame will be broadcast to all
  18578. nodes. The byte that’s “used internally” is used by the AppleTalk Manager to store
  18579. the address of the node sending the frame.
  18580.  
  18581. »Using ALAP
  18582.  
  18583. Most programs will never need to call ALAP, because higher-level protocols will
  18584. automatically call ALAP as necessary. If you do want to send a frame directly via an
  18585. ALAP, call the WriteLAP function. There’s no ReadLAP function in assembly language;
  18586. if you want to read ALAP frames, you must call AttachPH to add your protocol handler
  18587. to the node’s protocol handler table. The ALAP module will examine every incoming
  18588. frame and call your protocol handler for each frame received with the correct ALAP
  18589. protocol. When your program no longer wants to receive frames with a particular ALAP
  18590. protocol type value, it can call DetachPH to remove the corresponding protocol handler
  18591. from the protocol handler table.
  18592.  
  18593. See the “Protocol Handlers and Socket Listeners” section for information on how to
  18594. write a protocol handler.
  18595.  
  18596. »ALAP Routines
  18597.  
  18598. WriteLAP function
  18599.  
  18600. Parameter block
  18601.   -->    26    csCode      word     ;always writeLAP
  18602.   -->    30    wdsPointer  pointer  ;write data structure
  18603.  
  18604. WriteLAP sends a frame to another node. The frame data and destination of the frame
  18605. are described by the write data structure pointed to by wdsPointer. The first two
  18606. data bytes of an ALAP frame sent to another computer using the AppleTalk Manager must
  18607. indicate the length of the frame in bytes. The ALAP protocol type byte must be in the
  18608. range 1 to 127.
  18609.  
  18610. Result codes    noErr            No error
  18611.                 excessCollsns    No CTS received after 32 RTS’s
  18612.                 ddpLengthErr     Packet length exceeds maximum
  18613.                 lapProtErr       Invalid ALAP protocol type
  18614.  
  18615. AttachPH function
  18616.  
  18617. Parameter block
  18618.   -->    26    csCode    word     ;always attachPH
  18619.   -->    28    protType  byte     ;ALAP protocol type
  18620.   -->    30    handler   pointer  ;protocol handler
  18621.  
  18622. AttachPH adds the protocol handler pointed to by handler to the node’s protocol
  18623. table. ProtType specifies what kind of frame the protocol handler can service. After
  18624. AttachPH is called, the protocol handler is called for each incoming frame whose ALAP
  18625. protocol type equals protType.
  18626.  
  18627. Result codes    noErr         No error
  18628.                 lapProtErr    Error attaching protocol type
  18629.  
  18630. DetachPH function
  18631.  
  18632. Parameter block
  18633.   -->    26    csCode    word  ;always detachPH
  18634.   -->    28    protType  byte  ;ALAP protocol type
  18635.  
  18636. DetachPH removes from the node’s protocol table the specified ALAP protocol type and
  18637. corresponding protocol handler.
  18638.  
  18639. Result codes    noErr         No error
  18640.                 lapProtErr    Error detaching protocol type
  18641.  
  18642. _______________________________________________________________________________
  18643.  
  18644. »Datagram Delivery Protocol
  18645.  
  18646. »Data Structures
  18647.  
  18648. A DDP datagram consists of a header followed by up to 586 bytes of actual data
  18649. (Figure 8). The headers can be of two different lengths; they’re identified by the
  18650. following ALAP protocol types:
  18651.  
  18652.   shortDDP   .EQU    1    ;short DDP header
  18653.   longDDP    .EQU    2    ;long DDP header
  18654.  
  18655. •••Refer to Figure 8.•••
  18656.  
  18657. Figure 8–DDP Datagram
  18658.  
  18659. Long DDP headers (13 bytes) are used for sending datagrams between two or more different
  18660. AppleTalk networks. You can use the following global constants to access the contents
  18661. of a long DDP header:
  18662.  
  18663.   ddpHopCnt    .EQU    0    ;count of bridges passed (4 bits)
  18664.   ddpLength    .EQU    0    ;datagram length (10 bits)
  18665.   ddpChecksum  .EQU    2    ;checksum
  18666.   ddpDstNet    .EQU    4    ;destination network number
  18667.   ddpSrcNet    .EQU    6    ;source network number
  18668.   ddpDstNode   .EQU    8    ;destination node ID
  18669.   ddpSrcNode   .EQU    9    ;source node ID
  18670.   ddpDstSkt    .EQU    10   ;destination socket number
  18671.   ddpSrcSkt    .EQU    11   ;source socket number
  18672.   ddpType      .EQU    12   ;DDP protocol type
  18673.  
  18674. The size of a DDP long header is given by the following constant:
  18675.  
  18676.   ddpHSzLong   .EQU    ddpType+1
  18677.  
  18678. The short headers (five bytes) are used for datagrams sent to sockets within the same
  18679. network as the source socket. You can use the following global constants to access
  18680. the contents of a short DDP header:
  18681.  
  18682.   ddpLength    .EQU    0               ;datagram length
  18683.   sDDPDstSkt   .EQU    ddpChecksum     ;destination socket number
  18684.   sDDPSrcSkt   .EQU    sDDPDstSkt+1    ;source socket number
  18685.   sDDPType     .EQU    sDDPSrcSkt+1    ;DDP protocol type
  18686.  
  18687. The size of a DDP short header is given by the following constant:
  18688.  
  18689.   ddpHSzShort  .EQU    sDDPType+1
  18690.  
  18691. The datagram length is a ten-bit field. You can use the following global constant as
  18692. a mask for these bits:
  18693.  
  18694.   ddpLenMask   .EQU    $03FF
  18695.  
  18696. The following constant indicates the maximum length of a DDP datagram:
  18697.  
  18698.   ddpMaxData   .EQU    586
  18699.  
  18700. When you call DDP to send a datagram, you pass it information about the datagram in a
  18701. write data structure with the format shown in Figure 9.
  18702.  
  18703. •••Refer to Figure 9.•••
  18704.  
  18705. Figure 9–Write Data Structure for DDP
  18706.  
  18707. The first seven bytes are used internally for the ALAP header and the DDP datagram
  18708. length and checksum. The other bytes used internally store the network number, node
  18709. ID, and socket number of the socket client sending the datagram.
  18710.  
  18711. Warning:  The first entry in a DDP write data structure must begin at
  18712.           an odd address.
  18713.  
  18714. If you specify a node ID of 255, the datagram will be broadcast to all nodes within
  18715. the destination network. A network number of 0 means the local network to which the
  18716. node is connected.
  18717.  
  18718. Warning:  DDP always destroys the high-order byte of the destination
  18719.           network number when it sends a datagram with a short header.
  18720.           Therefore, if you want to reuse the first entry of a DDP write
  18721.           data structure entry, you must restore the destination network number.
  18722.  
  18723. »Using DDP
  18724.  
  18725. Before it can use a socket, the program must call OpenSkt, which adds a socket and
  18726. its socket listener to the socket table. When a client is finished using a socket,
  18727. call CloseSkt, which removes the socket’s entry from the socket table. To send a
  18728. datagram via DDP, call WriteDDP. If you want to read DDP datagrams, you must write
  18729. your own socket listener. DDP will send every incoming datagram for that socket to
  18730. your socket listener.
  18731.  
  18732. See the “Protocol Handlers and Socket Listeners” section for information on how to
  18733. write a socket listener.
  18734.  
  18735. »DDP Routines
  18736.  
  18737. OpenSkt function
  18738.  
  18739. Parameter block
  18740.   -->    26    csCode    word     ;always openSkt
  18741.   <->    28    socket    byte     ;socket number
  18742.   -->    30    listener  pointer  ;socket listener
  18743.  
  18744. OpenSkt adds a socket and its socket listener to the socket table. If the socket
  18745. parameter is nonzero, it must be in the range 64 to 127, and it specifies the socket’s
  18746. number; if socket is 0, OpenSkt opens a socket with a socket number in the range 128
  18747. to 254, and returns it in the socket parameter. Listener contains a pointer to the
  18748. socket listener.
  18749.  
  18750. OpenSkt will return ddpSktErr if you pass the number of an already opened socket, if
  18751. you pass a socket number greater than 127, or if the socket table is full (the socket
  18752. table can hold a maximum of 12 sockets).
  18753.  
  18754. Result codes    noErr        No error
  18755.                 ddpSktErr    Socket error
  18756.  
  18757. CloseSkt function
  18758.  
  18759. Parameter block
  18760.   -->    26    csCode  word  ;always closeSkt
  18761.   -->    28    socket  byte  ;socket number
  18762.  
  18763. CloseSkt removes the entry of the specified socket from the socket table. If you pass
  18764. a socket number of 0, or if you attempt to close a socket that isn’t open, CloseSkt
  18765. will return ddpSktErr.
  18766.  
  18767. Result codes    noErr        No error
  18768.                 ddpSktErr    Socket error
  18769.  
  18770. WriteDDP function
  18771.  
  18772. Parameter block
  18773.   -->    26    csCode        word     ;always writeDDP
  18774.   -->    28    socket        byte     ;socket number
  18775.   -->    29    checksumFlag  byte     ;checksum flag
  18776.   -->    30    wdsPointer    pointer  ;write data structure
  18777.  
  18778. WriteDDP sends a datagram to another socket. WDSPointer points to a write data structure
  18779. containing the datagram and the address of the destination socket. If checksumFlag is
  18780. TRUE, WriteDDP will compute the checksum for all datagrams requiring long headers.
  18781.  
  18782. Result codes    noErr          No error
  18783.                 ddpLenErr      Datagram length too big
  18784.                 ddpSktErr      Socket error
  18785.                 noBridgeErr    No bridge found
  18786.  
  18787. _______________________________________________________________________________
  18788.  
  18789. »AppleTalk Transaction Protocol
  18790.  
  18791. »Data Structures
  18792.  
  18793. An ATP packet consists of an ALAP header, DDP header, and ATP header, followed by
  18794. actual data (Figure 10). You can use the following global constants to access the
  18795. contents of an ATP header:
  18796.  
  18797.   atpControl   .EQU    0    ;control information
  18798.   atpBitMap    .EQU    1    ;bit map
  18799.   atpRespNo    .EQU    1    ;sequence number
  18800.   atpTransID   .EQU    2    ;transaction ID
  18801.   atpUserData  .EQU    4    ;user bytes
  18802.  
  18803. The size of an ATP header is given by the following constant:
  18804.  
  18805.   atpHdSz      .EQU    8
  18806.  
  18807. •••Refer to Figure 10.•••
  18808.  
  18809. Figure 10–ATP Packet
  18810.  
  18811. ATP packets are identified by the following DDP protocol type:
  18812.  
  18813.   atp          .EQU    3
  18814.  
  18815. The control information contains a function code and various control bits. The function
  18816. code identifies either a TReq, TResp, or TRel packet with one of the following global
  18817. constants:
  18818.  
  18819.   atpReqCode   .EQU    $40    ;TReq packet
  18820.   atpRspCode   .EQU    $80    ;TResp packet
  18821.   atpRelCode   .EQU    $C0    ;TRel packet
  18822.  
  18823. The send-transmission-status, end-of-message, and exactly-once bits in the control
  18824. information are accessed via the following global constants:
  18825.  
  18826.   atpSTSBit    .EQU    3    ;send-transmission-status bit
  18827.   atpEOMBit    .EQU    4    ;end-of-message bit
  18828.   atpXOBit     .EQU    5    ;exactly-once bit
  18829.  
  18830. Many ATP calls require a field called atpFlags (Figure 11), which contains the above
  18831. three bits plus the following two bits:
  18832.  
  18833.   sendChk      .EQU    0    ;send-checksum bit
  18834.   tidValid     .EQU    1    ;transaction ID validity bit
  18835.  
  18836. •••Refer to Figure 11.•••
  18837.  
  18838. Figure 11–ATPFlags Field
  18839.  
  18840. The maximum number of response packets in an ATP transaction is given by the following
  18841. global constant:
  18842.  
  18843.   atpMaxNum    .EQU    8
  18844.  
  18845. When you call ATP to send responses, you pass the responses in a response BDS, which
  18846. is a list of up to eight elements, each of which contains the following:
  18847.  
  18848.   bdsBuffSz    .EQU    0    ;size of data to send
  18849.   bdsBuffAddr  .EQU    2    ;pointer to data
  18850.   bdsUserData  .EQU    8    ;user bytes
  18851.  
  18852. When you call ATP to receive responses, you pass it a response BDS with up to eight
  18853. elements, each in the following format:
  18854.  
  18855.   bdsBuffSz    .EQU    0    ;buffer size in bytes
  18856.   bdsBuffAddr  .EQU    2    ;pointer to buffer
  18857.   bdsDataSz    .EQU    6    ;number of bytes actually received
  18858.   bdsUserData  .EQU    8    ;user bytes
  18859.  
  18860. The size of a BDS element is given by the following constant:
  18861.  
  18862.   bdsEntrySz   .EQU    12
  18863.  
  18864. ATP clients are identified by internet addresses in the form shown in Figure 12.
  18865.  
  18866. •••Refer to Figure 12.•••
  18867.  
  18868. Figure 12–Internet Address
  18869.  
  18870. »Using ATP
  18871.  
  18872. Before you can use ATP on a Macintosh 128K, the .ATP driver must be read from the
  18873. system resource file via a Device Manager Open call. The name of the .ATP driver is
  18874. '.ATP' and its reference number is –11. When the .ATP driver is opened, it reads its
  18875. ATP code into the application heap and installs a task into the vertical retrace
  18876. queue.
  18877.  
  18878. Warning:  When another application starts up, the application heap is
  18879.           reinitialized; on a Macintosh 128K, this means that the ATP
  18880.           code is lost (and must be reloaded by the next application).
  18881.  
  18882. When you’re through using ATP on a Macintosh 128K, call the Device Manager Close
  18883. routine—the system will be returned to the state it was in before the
  18884. .ATP driver was opened.
  18885.  
  18886. On a Macintosh 512K or XL, the .ATP driver will have been loaded into the system heap
  18887. either at system startup or upon execution of a Device Manager Open call loading MPP.
  18888. You shouldn’t close the .ATP driver on a Macintosh 512K or XL; AppleTalk expects it
  18889. to remain open on these systems.
  18890.  
  18891. To send a request to another socket and get a response, call SendRequest. The call
  18892. terminates when either an entire response is received or a specified retry timeout
  18893. interval elapses. To open a socket for the purpose of responding to requests, call
  18894. OpenATPSkt. Then call GetRequest to receive a request; when a request is received,
  18895. the call is completed. After receiving and servicing a request, call SendResponse to
  18896. return response information. If you cannot or do not want to send the entire response
  18897. all at once, make a SendResponse call to send some of the response, and then call
  18898. AddResponse later to send the remainder of the response. To close a socket opened for
  18899. the purpose of sending responses, call CloseATPSkt.
  18900.  
  18901. During exactly-once transactions, SendResponse doesn’t terminate until the transaction
  18902. is completed via a TRel packet, or the retry count is exceeded.
  18903.  
  18904. Warning:  Don’t modify the parameter block passed to an ATP call until
  18905.           the call is completed.
  18906.  
  18907. »ATP Routines
  18908.  
  18909. OpenATPSkt function
  18910.  
  18911. Parameter block
  18912.   -->    26    csCode     word       ;always openATPSkt
  18913.   <->    28    atpSocket  byte       ;socket number
  18914.   -->    30    addrBlock  long word  ;socket request specification
  18915.  
  18916. OpenATPSkt opens a socket for the purpose of receiving requests. ATPSocket contains
  18917. the socket number of the socket to open. If it’s 0, a number is dynamically assigned
  18918. and returned in atpSocket. AddrBlock contains a specification of the socket addresses
  18919. from which requests will be accepted. A 0 in the network number, node ID, or socket
  18920. number field of addrBlock means that requests will be accepted from every network,
  18921. node, or socket, respectively.
  18922.  
  18923. Result codes    noErr          No error
  18924.                 tooManySkts    Too many responding sockets
  18925.                 noDataArea     Too many outstanding ATP calls
  18926.  
  18927. CloseATPSkt function
  18928.  
  18929. Parameter block
  18930.   -->    26    csCode     word    ;always closeATPSkt
  18931.   -->    28    atpSocket  byte    ;socket number
  18932.  
  18933. CloseATPSkt closes the socket whose number is specified by atpSocket, for the purpose
  18934. of receiving requests.
  18935.  
  18936. Result codes    noErr         No error
  18937.                 noDataArea    Too many outstanding ATP calls
  18938.  
  18939. SendRequest function
  18940.  
  18941. Parameter block
  18942.   -->    18    userData    long word  ;user bytes
  18943.   <--    22    reqTID      word       ;transaction ID used in request
  18944.   -->    26    csCode      word       ;always sendRequest
  18945.   <--    28    currBitMap  byte       ;bit map
  18946.   <->    29    atpFlags    byte       ;control information
  18947.   -->    30    addrBlock   long word  ;destination socket address
  18948.   -->    34    reqLength   word       ;request size in bytes
  18949.   -->    36    reqPointer  pointer    ;pointer to request data
  18950.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  18951.   -->    44    numOfBuffs  byte       ;number of responses expected
  18952.   -->    45    timeOutVal  byte       ;timeout interval
  18953.   <--    46    numOfResps  byte       ;number of responses received
  18954.   <->    47    retryCount  byte       ;number of retries
  18955.  
  18956. SendRequest sends a request to another socket and waits for a response. UserData
  18957. contains the four user bytes. AddrBlock indicates the socket to which the request
  18958. should be sent. ReqLength and reqPointer contain the size and location of the request
  18959. to send. BDSPointer points to a response BDS where the responses are to be returned;
  18960. numOfBuffs indicates the number of responses requested. The number of responses
  18961. received is returned in numOfResps. If a nonzero value is returned in numOfResps, you
  18962. can examine currBitMap to determine which packets of the transaction were actually
  18963. received and to detect pieces for higher-level recovery, if desired.
  18964.  
  18965. TimeOutVal indicates the number of seconds that SendRequest should wait for a response
  18966. before resending the request. RetryCount indicates the maximum number of retries
  18967. SendRequest should attempt. The end-of-message flag of atpFlags will be set if the
  18968. EOM bit is set in the last packet received in a valid response sequence. The exactly-once
  18969. flag should be set if you want the request to be part of an exactly-once transaction.
  18970.  
  18971. To cancel a SendRequest call, you need the transaction ID; it’s returned in reqTID.
  18972. You can examine reqTID before the completion of the call, but its contents are valid
  18973. only after the tidValid bit of atpFlags has been set.
  18974.  
  18975. SendRequest completes when either an entire response is received or the retry count
  18976. is exceeded.
  18977.  
  18978. Note:  The value provided in retryCount will be modified during SendRequest
  18979.        if any retries are made. This field is used to monitor the number of
  18980.        retries; for each retry, it’s decremented by 1.
  18981.  
  18982. Result codes    noErr          No error
  18983.                 reqFailed      Retry count exceeded
  18984.                 tooManyReqs    Too many concurrent requests
  18985.                 noDataArea     Too many outstanding ATP calls
  18986.                 reqAborted     Request canceled by user
  18987.  
  18988. GetRequest function
  18989.  
  18990. Parameter block
  18991.   <--    18    userData    long word  ;user bytes
  18992.   -->    26    csCode      word       ;always getRequest
  18993.   -->    28    atpSocket   byte       ;socket number
  18994.   <--    29    atpFlags    byte       ;control information
  18995.   <--    30    addrBlock   long word  ;source of request
  18996.   <->    34    reqLength   word       ;request buffer size
  18997.   -->    36    reqPointer  pointer    ;pointer to request buffer
  18998.   <--    44    bitMap      byte       ;bit map
  18999.   <--    46    transID     word       ;transaction ID
  19000.  
  19001. GetRequest sets up the mechanism to receive a request sent by a SendRequest call.
  19002. UserData returns the four user bytes from the request. ATPSocket contains the socket
  19003. number of the socket that should listen for a request. The internet address of the
  19004. socket from which the request was sent is returned in addrBlock. ReqLength and reqPointer
  19005. indicate the size (in bytes) and location of a buffer to store the incoming request.
  19006. The actual size of the request is returned in reqLength. The transaction bit map and
  19007. transaction ID will be returned in bitMap and transID. The exactly-once flag in
  19008. atpFlags will be set if the request is part of an exactly-once transaction.
  19009.  
  19010. GetRequest completes when a request is received.
  19011.  
  19012. Result codes    noErr        No error
  19013.                 badATPSkt    Bad responding socket
  19014.  
  19015. SendResponse function
  19016.  
  19017. Parameter block
  19018.   <--    18    userData    long word  ;user bytes from TRel
  19019.   <--    22    reqTID      word       ;transaction ID used in request
  19020.   -->    26    csCode      word       ;always sendResponse
  19021.   -->    28    atpSocket   byte       ;socket number
  19022.   -->    29    atpFlags    byte       ;control information
  19023.   -->    30    addrBlock   long word  ;response destination
  19024.   -->    40    bdsPointer  pointer    ;pointer to response BDS
  19025.   -->    44    numOfBuffs  byte       ;number of response packets being sent
  19026.   -->    45    bdsSize     byte       ;BDS size in elements
  19027.   -->    46    transID     word       ;transaction ID
  19028.  
  19029. SendResponse sends a response to a socket. If the response was part of an exactly-once
  19030. transaction, userData will contain the user bytes from the TRel packet. ATPSocket
  19031. contains the socket number from which the response should be sent. The end-of-message
  19032. flag in atpFlags should be set if the response contains the final packet in a transaction
  19033. composed of a group of packets and the number of responses is less than requested.
  19034. AddrBlock indicates the address of the socket to which the response should be sent.
  19035. BDSPointer points to a response BDS containing room for the maximum number of responses
  19036. to be sent; bdsSize contains this maximum number. NumOfBuffs contains the number of
  19037. response packets to be sent in this call; you may wish to make AddResponse calls to
  19038. complete the response. TransID indicates the transaction ID of the associated request.
  19039.  
  19040. During exactly-once transactions, SendResponse doesn’t complete until either a TRel
  19041. packet is received from the socket that made the request, or the retry count is
  19042. exceeded.
  19043.  
  19044. Result codes    noErr         No error
  19045.                 badATPSkt     Bad responding socket
  19046.                 noRelErr      No release received
  19047.                 noDataArea    Too many outstanding ATP calls
  19048.                 badBuffNum    Sequence number out of range
  19049.  
  19050. AddResponse function
  19051.  
  19052. Parameter block
  19053.   -->    18    userData    long word  ;user bytes
  19054.   -->    26    csCode      word       ;always addResponse
  19055.   -->    28    atpSocket   byte       ;socket number
  19056.   -->    29    atpFlags    byte       ;control information
  19057.   -->    30    addrBlock   long word  ;response destination
  19058.   -->    34    reqLength   word       ;response size
  19059.   -->    36    reqPointer  pointer    ;pointer to response
  19060.   -->    44    rspNum      byte       ;sequence number
  19061.   -->    46    transID     word       ;transaction ID
  19062.  
  19063. AddResponse sends an additional response packet to a socket that has already been
  19064. sent the initial part of a response via SendResponse. UserData contains the four user
  19065. bytes. ATPSocket contains the socket number from which the response should be sent.
  19066. The end-of-message flag in atpFlags should be set if this response packet is the
  19067. final packet in a transaction composed of a group of packets and the number of responses
  19068. is less than requested. AddrBlock indicates the socket to which the response should
  19069. be sent. ReqLength and reqPointer contain the size (in bytes) and location of the
  19070. response to send; rspNum indicates the sequence number of the response (in the range
  19071. 0 to 7). TransID must contain the transaction ID.
  19072.  
  19073. Warning:  If the transaction is part of an exactly-once transaction, the
  19074.           buffer used in the AddResponse call must not be altered or
  19075.           released until the corresponding SendResponse call has completed.
  19076.  
  19077. Result codes    noErr         No error
  19078.                 badATPSkt     Bad responding socket
  19079.                 noSendResp    AddResponse issued before SendResponse
  19080.                 badBuffNum    Sequence number out of range
  19081.                 noDataArea    Too many outstanding ATP calls
  19082.  
  19083. RelTCB function
  19084.  
  19085. Parameter block
  19086.   -->    26    csCode     word       ;always relTCB
  19087.   -->    30    addrBlock  long word  ;destination of request
  19088.   -->    46    transID    word       ;transaction ID of request
  19089.  
  19090. RelTCB dequeues the specified SendRequest call and returns the result code reqAborted
  19091. for the aborted call. The transaction ID can be obtained from the reqTID field of the
  19092. SendRequest queue entry; see the description of SendRequest for details.
  19093.  
  19094. Result codes    noErr         No error
  19095.                 cbNotFound    ATP control block not found
  19096.                 noDataArea    Too many outstanding ATP calls
  19097.  
  19098. RelRspCB function
  19099.  
  19100. Parameter block
  19101.   -->    26    csCode     word      ;always relRspCB
  19102.   -->    28    atpSocket  byte      ;socket number that request was received on
  19103.   -->    30    addrBlock  long word ;source of request
  19104.   -->    46    transID    word      ;transaction ID of request
  19105.  
  19106. In an exactly-once transaction, RelRspCB cancels the specified SendResponse, without
  19107. waiting for the release timer to expire or a TRel packet to be received. No error is
  19108. returned for the SendResponse call. Whan called to cancel a transaction that isn’t
  19109. using exactly-once service, RelRspCB returns cbNotFound. The transaction ID can be
  19110. obtained from the reqTID field of the SendResponse queue entry; see the description
  19111. of SendResponse for details.
  19112.  
  19113. Result codes    noErr         No error
  19114.                 cbNotFound    ATP control block not found
  19115.  
  19116. _______________________________________________________________________________
  19117.  
  19118. »Name-Binding Protocol
  19119.  
  19120. »Data Structures
  19121.  
  19122. The first two bytes in the NBP header (Figure 13) indicate the type of the packet,
  19123. the number of tuples in the packet, and an NBP packet identifier. You can use the
  19124. following global constants to access these bytes:
  19125.  
  19126.   nbpControl  .EQU    0    ;packet type
  19127.   nbpTCount   .EQU    0    ;tuple count
  19128.   nbpID       .EQU    1    ;packet identifier
  19129.   nbpTuple    .EQU    2    ;start of first tuple
  19130.  
  19131. •••Refer to Figure 13.•••
  19132.  
  19133. Figure 13–NBP Packet
  19134.  
  19135. NBP packets are identified by the following DDP protocol type:
  19136.  
  19137.   nbp         .EQU    2
  19138.  
  19139. NBP uses the following global constants in the nbpControl field to identify NBP
  19140. packets:
  19141.  
  19142.   brRq        .EQU    1    ;broadcast request
  19143.   lkUp        .EQU    2    ;lookup request
  19144.   lkUpReply   .EQU    3    ;lookup reply
  19145.  
  19146. NBP entities are identified by internet address in the form shown in Figure 14 below.
  19147. Entities are also identified by tuples, which include both an internet address and an
  19148. entity name. You can use the following global constants to access information in
  19149. tuples:
  19150.  
  19151.   tupleNet    .EQU    0    ;network number
  19152.   tupleNode   .EQU    2    ;node ID
  19153.   tupleSkt    .EQU    3    ;socket number
  19154.   tupleEnum   .EQU    4    ;used internally
  19155.   tupleName   .EQU    5    ;entity name
  19156.  
  19157. The meta-characters in an entity name can be identified with the following global
  19158. constants:
  19159.  
  19160.   equals      .EQU    '='    ;“wild-card” meta-character
  19161.   star        .EQU    '*'    ;“this zone” meta-character
  19162.  
  19163. •••Refer to Figure 14.•••
  19164.  
  19165. Figure 14–Names Table Entry
  19166.  
  19167. The maximum number of tuples in an NBP packet is given by the following global constant:
  19168.  
  19169.   tupleMax    .EQU    15
  19170.  
  19171. Entity names are mapped to sockets via the names table. Each entry in the names table
  19172. has the structure shown in Figure 14.
  19173.  
  19174. You can use the following global constants to access some of the elements of a names
  19175. table entry:
  19176.  
  19177.   ntLink      .EQU    0    ;pointer to next entry
  19178.   ntTuple     .EQU    4    ;tuple
  19179.   ntSocket    .EQU    7    ;socket number
  19180.   ntEntity    .EQU    9    ;entity name
  19181.  
  19182. The socket number of the names information socket is given by the following global
  19183. constant:
  19184.  
  19185.   nis         .EQU    2
  19186.  
  19187. »Using NBP
  19188.  
  19189. On a Macintosh 128K, before calling any other NBP routines, call the LoadNBP function,
  19190. which reads the NBP code from the system resource file into the application heap.
  19191. (The NBP code is part of the .MPP driver, which has a driver reference number of
  19192. –10.) When you’re finished with NBP and want to reclaim the space its code occupies,
  19193. call UnloadNBP. On a Macintosh 512K or XL, the NBP code is read in when the .MPP
  19194. driver is loaded.
  19195.  
  19196. Warning:  When an application starts up, the application heap is
  19197.           reinitialized; on a Macintosh 128K, this means that the
  19198.           NBP code is lost (and must be reloaded by the next application).
  19199.  
  19200. When an entity wants to communicate via an AppleTalk network, it should call RegisterName
  19201. to place its name and internet address in the names table. When an entity no longer
  19202. wants to communicate on the network, or is being shut down, it should call RemoveName
  19203. to remove its entry from the names table.
  19204.  
  19205. To determine the address of an entity you know only by name, call LookupName, which
  19206. returns a list of all entities with the name you specify. If you already know the
  19207. address of an entity, and want only to confirm that it still exists, call ConfirmName.
  19208. ConfirmName is more efficient than LookupName in terms of network traffic.
  19209.  
  19210. »NBP Routines
  19211.  
  19212. RegisterName function
  19213.  
  19214. Parameter block
  19215.   -->    26    csCode      word     ;always registerName
  19216.   -->    28    interval    byte     ;retry interval
  19217.   <->    29    count       byte     ;retry count
  19218.   -->    30    ntQElPtr    pointer  ;names table element pointer
  19219.   -->    34    verifyFlag  byte     ;set if verify needed
  19220.  
  19221. RegisterName adds the name and address of an entity to the node’s names table. NTQElPtr
  19222. points to a names table entry containing the entity’s name and internet address (in
  19223. the form shown in Figure 14 above). Meta-characters aren’t allowed in the object and
  19224. type fields of the entity name; the zone field, however, must contain the meta-character
  19225. “*”. If verifyFlag is TRUE, RegisterName checks on the network to see if the name is
  19226. already in use, and returns a result code of nbpDuplicate if so. Interval and count
  19227. contain the retry interval in eight-tick units and the retry count. When a retry is
  19228. made, the count field is modified.
  19229.  
  19230. •••Refer to Technical Note #225:•••
  19231.  
  19232. Warning:  The names table entry passed to RegisterName remains the
  19233.           property of NBP until removed from the names table. Don’t
  19234.           attempt to remove or modify it. If you’ve allocated memory
  19235.           using a NewHandle call, you must lock it as long as the name
  19236.           is registered.
  19237.  
  19238. Warning:  VerifyFlag should normally be set before calling RegisterName.
  19239.  
  19240. Result codes    noErr           No error
  19241.                 nbpDuplicate    Duplicate name already exists
  19242.                 nbpNISErr       Error opening names information socket
  19243.  
  19244. LookupName function
  19245.  
  19246. Parameter block
  19247.   -->    26    csCode       word     ;always lookupName
  19248.   -->    28    interval     byte     ;retry interval
  19249.   <->    29    count        byte     ;retry count
  19250.   -->    30    entityPtr    pointer  ;pointer to entity name
  19251.   -->    34    retBuffPtr   pointer  ;pointer to buffer
  19252.   -->    38    retBuffSize  word     ;buffer size in bytes
  19253.   -->    40    maxToGet     word     ;matches to get
  19254.   <--    42    numGotten    word     ;matches found
  19255.  
  19256. LookupName returns the addresses of all entities with a specified name. EntityPtr
  19257. points to the entity’s name (in the form shown in Figure 14 above). Meta-characters
  19258. are allowed in the entity name. RetBuffPtr and retBuffSize contain the location and
  19259. size of an area of memory in which the tuples describing the entity names and their
  19260. corresponding addresses should be returned. MaxToGet indicates the maximum number of
  19261. matching names to find addresses for; the actual number of addresses found is returned
  19262. in numGotten. Interval and count contain the retry interval and the retry count.
  19263. LookupName completes when either the number of matches is equal to or greater than
  19264. maxToGet, or the retry count has been exceeded. The count field is decremented for
  19265. each retransmission.
  19266.  
  19267. Note:  NumGotten is first set to 0 and then incremented with each match
  19268.        found. You can test the value in this field, and can start examining
  19269.        the received addresses in the buffer while the lookup continues.
  19270.  
  19271. Result codes    noErr         No error
  19272.                 nbpBuffOvr    Buffer overflow
  19273.  
  19274. ConfirmName function
  19275.  
  19276. Parameter block
  19277.   -->    26    csCode       word     ;always confirmName
  19278.   -->    28    interval     byte     ;retry interval
  19279.   <->    29    count        byte     ;retry count
  19280.   -->    30    entityPtr    pointer  ;pointer to entity name
  19281.   -->    34    confirmAddr  pointer  ;entity address
  19282.   <--    38    newSocket    byte     ;socket number
  19283.  
  19284. ConfirmName confirms that an entity known by name and address still exists (is still
  19285. entered in the names directory). EntityPtr points to the entity’s name
  19286. (in the form shown in Figure 14 above). ConfirmAddr specifies the address to confirmed.
  19287. No meta-characters are allowed in the entity name. Interval and count contain the
  19288. retry interval and the retry count. The socket number of the entity is returned in
  19289. newSocket. ConfirmName is more efficient than LookupName in terms of network traffic.
  19290.  
  19291. Result codes    noErr           No error
  19292.                 nbpConfDiff     Name confirmed for different socket
  19293.                 nbpNoConfirm    Name not confirmed
  19294.  
  19295. RemoveName function
  19296.  
  19297. Parameter block
  19298.   -->    26    csCode     word     ;always removeName
  19299.   -->    30    entityPtr  pointer  ;pointer to entity name
  19300.  
  19301. RemoveName removes an entity name from the names table of the given entity’s node.
  19302.  
  19303. Result codes    noErr          No error
  19304.                 nbpNotFound    Name not found
  19305.  
  19306. LoadNBP function
  19307.  
  19308. Parameter block
  19309.   -->    26    csCode  word  ;always loadNBP
  19310.  
  19311. On a Macintosh 128K, LoadNBP reads the NBP code from the system resource file into
  19312. the application heap; on a Macintosh 512K or XL it has no effect.
  19313.  
  19314. Result codes    noErr    No error
  19315.  
  19316. UnloadNBP function
  19317.  
  19318. Parameter block
  19319.   -->    26    csCode  word  ;always unloadNBP
  19320.  
  19321. On a Macintosh 128K, UnloadNBP makes the NBP code purgeable; the space isn’t actually
  19322. released by the Memory Manager until necessary. On a Macintosh 512K or XL, UnloadNBP
  19323. has no effect.
  19324.  
  19325. Result codes    noErr    No error
  19326.  
  19327. _______________________________________________________________________________
  19328.  
  19329.  
  19330. æKY Extended…Protocol…Package…Driver
  19331. æC »EXTENDED PROTOCOL PACKAGE DRIVER                         AppleTalkManager
  19332. _______________________________________________________________________________
  19333.  
  19334. The Extended Protocol Package (XPP) driver is intended to implement several AppleTalk
  19335. communication protocols in the same package for ease of use.  The
  19336. .XPP driver currently consists of two modules that operate on two levels: the low-level
  19337. module implements the workstation side of AppleTalk Session Protocol, and the high-level
  19338. module implements a small portion of the workstation side of the AppleTalk Filing
  19339. Protocol.
  19340.  
  19341. This driver adds functionality to the AppleTalk manager by providing services additional
  19342. to those provided in the .MPP and .ATP drivers.  Figure 2 shows the Macintosh AppleTalk
  19343. drivers and the protocols accessible through each driver.
  19344.  
  19345. The .XPP driver maps an AFP call from the client workstation into one or more ASP
  19346. calls. .XPP provides one client-level call for AFP.
  19347.  
  19348. The implementation of AFP in the .XPP driver is very limited.  Most calls are a very
  19349. simple one-to-one mapping from an AFP call to an ASP command without any interpretation
  19350. of the syntax of the AFP command by the .XPP driver.  Refer to the “Mapping AFP
  19351. Commands” section of this chapter for further information.
  19352.  
  19353. _______________________________________________________________________________
  19354.  
  19355. »Version
  19356.  
  19357. The .XPP driver supports ASP Version (hex) $100, as described in Inside AppleTalk.
  19358.  
  19359. _______________________________________________________________________________
  19360.  
  19361. »Error Reporting
  19362.  
  19363. Errors are returned by the .XPP driver in the ioResult field of the Device Manager
  19364. Control calls.
  19365.  
  19366. The error conditions reported by the .XPP driver may represent the unsuccessful
  19367. completion of a routine in more than just one process involved in the interaction of
  19368. the session.   System-level, .XPP driver, AppleTalk, and server errors can all turn
  19369. up in the ioResult field.
  19370.  
  19371. AFP calls return codes indicating the unsuccessful completion of AFP commands in the
  19372. Command Result field of the parameter block (described below).
  19373.  
  19374. An application using the .XPP driver should  respond appropriately to error conditions
  19375. reported from the different parts of the interaction.  As shown in Figure 3, the
  19376. following errors can be returned in the ioResult field:
  19377.  
  19378.   1.  System-level errors
  19379.  
  19380.       System errors returned by the .XPP driver indicate such conditions
  19381.       as the driver not being open or a specific system call not being
  19382.       supported. For a complete list of result codes returned by the
  19383.       Macintosh system software, refer to Appendix A.
  19384.  
  19385.   2.  XPP errors (for example, “Session not opened”)
  19386.  
  19387.       The .XPP driver can also return errors resulting from its own
  19388.       activity (for example, the referenced session isn’t open).  The
  19389.       possible .XPP driver errors returned are listed in the .XPP driver
  19390.       results codes section with each function that can return the code.
  19391.  
  19392.   3.  AppleTalk Errors (returned from lower-level protocols)
  19393.  
  19394.       .XPP may also return errors from lower-level protocols (for example,
  19395.       “Socket not open”).  Possible error conditions and codes are described
  19396.       elsewhere in this chapter.
  19397.  
  19398.   4.  An  ASP-specific error could be returned from an ASP server in
  19399.       response to a failed OpenSession call.  Errors of this type, returned
  19400.       by the server to the workstation, are documented both in Inside
  19401.       AppleTalk, section 11,  “AppleTalk Session Protocol”, and in the .XPP
  19402.       driver results code section of this chapter.
  19403.  
  19404.   5.  The AppleTalk Filing Protocol defines errors that are returned from
  19405.       the server to the workstation client.  These errors are returned in
  19406.       the cmdResult field of the parameter block (error type 5 in Figure 15).
  19407.       This field is valid if no system-level error is returned by the call.
  19408.       Note that at the ASP level, the cmdResult field is client-defined data
  19409.       and may not be an error code.
  19410.  
  19411. •••Refer to Figure 15.•••
  19412.  
  19413. Figure 15–Error Reporting
  19414.  
  19415. _______________________________________________________________________________
  19416.  
  19417. ».XPP Driver Functions Overview
  19418.  
  19419. The paragraphs below describe the implementation of ASP in the .XPP driver.  For more
  19420. detailed information about ASP, refer to Inside AppleTalk, Section 11, “AppleTalk
  19421. Session Protocol (ASP)”.
  19422.  
  19423. »Using AppleTalk Name Binding Protocol
  19424.  
  19425. A server wishing to advertise its service on the AppleTalk network calls ATP to open
  19426. an ATP responding socket known as the session listening socket (SLS).  The server
  19427. then calls the Name Binding Protocol (NBP) to register a name on this socket.  At
  19428. this point, the server calls the server side of ASP to pass it the address of the
  19429. SLS.  Then,  the server starts listening on the SLS for session opening requests
  19430. coming over the network.
  19431.  
  19432. »Opening and Closing Sessions
  19433.  
  19434. When a workstation wishes to access a server, the workstation must call NBP to discover
  19435. the SLS for that server.  Then the workstation calls ASP to open a session with that
  19436. server.
  19437.  
  19438. After determining the SLS (address) of the server, the workstation client issues an
  19439. OpenSession (or AFPLogin) call to open a session with that server.  As a result of
  19440. this call, ASP sends a special OpenSession packet (an ATP request) to the SLS; this
  19441. packet carries the address of a workstation socket for use in the session.   This
  19442. socket is referred to as the workstation session socket (WSS).  If the server is
  19443. unable to set up the session, it returns an error.  If the request is successful, the
  19444. server returns no error, and the session is opened.  The open session packet also
  19445. contains a version number so that both ends can verify that they are speaking the
  19446. same version of ASP.
  19447.  
  19448. The AbortOS function can be used to abort an outstanding OpenSession request before
  19449. it has completed.
  19450.  
  19451. The workstation client closes the session by issuing a CloseSession (or AFPLogout). 
  19452. The CloseSession call aborts any calls that are active on the session and closes the
  19453. session.  The session can also be closed by the server or by ASP itself, such as when
  19454. one end of the session fails.  The CloseAll call (which should be used with care)
  19455. aborts every session that the driver has active.
  19456.  
  19457. »Session Maintenance
  19458.  
  19459. A session will remain open until it is explicitly terminated by the ASP client at
  19460. either end or until one of the sessions ends, fails, or becomes unreachable.
  19461.  
  19462. »Commands on an Open Session
  19463.  
  19464. Once a session has been opened, the workstation client can send a sequence of commands
  19465. over the session to the server end.  The commands are delivered in the same order as
  19466. they are issued at the workstation end, and replies to the commands are returned to
  19467. the workstation end.
  19468.  
  19469. Three types of commands can be made on an open session.  These commands are UserCommand,
  19470. UserWrite, and AFPCall functions described in the following paragraphs.
  19471.  
  19472. UserCommand calls are similar to ATP requests.  The workstation client sends a command
  19473. (included in a variable size command block) to the server client requesting it to
  19474. perform a particular function and send back a variable size command reply.  Examples
  19475. of such commands vary from a request to open a particular file on a file server, to
  19476. reading a certain range of bytes from a device.  In the first case, a small amount of
  19477. reply data is returned; in the second case a multiple-packet reply might be generated.
  19478.  
  19479. The .XPP driver does not interpret the command block or in any way participate in
  19480. executing the command’s function.  It simply conveys the command block, included in a
  19481. higher-level format, to the server end of the session, and returns the command reply
  19482. to the workstation-end client.  The command reply consists of a four-byte command
  19483. result and a variable size command reply block.
  19484.  
  19485. UserWrite allows the workstation to convey blocks of data to the server.  UserWrite
  19486. is used to transfer a variable size block of data to the server end of the session
  19487. and to receive a reply.
  19488.  
  19489. The AFPCall function provides a mechanism for passing an AFP command to the server
  19490. end of an open session and receiving a reply.  The first byte of the AFPCall command
  19491. buffer contains the code for the AFP command that is to be passed to the server for
  19492. execution.  Most AFP calls are implemented through a very simple one-to-one mapping
  19493. that takes the call and makes an ASP command out of it.
  19494.  
  19495. The AFPCall function can have one of four different, but very similar, formats.
  19496.  
  19497. »Getting Server Status Information
  19498.  
  19499. ASP provides a service to allow its workstation clients to obtain a block of service
  19500. status information from a server without the need for opening a session.   The GetStatus
  19501. function  returns a status block from the server identified by the indicated address.
  19502.  ASP does not impose any structure on the status block.  This structure is defined by
  19503. the protocol above ASP.
  19504.  
  19505. »Attention Mechanism
  19506.  
  19507. Attentions are defined in ASP as a way for the server to alert the workstation of
  19508. some event or critical piece of information.  The ASP OpenSession and AFPLogin calls
  19509. include a pointer to an attention routine in their parameter blocks.  This attention
  19510. routine is called by the .XPP driver when it receives an attention from the server
  19511. and also when the session is closing as described below.
  19512.  
  19513. In addition, upon receiving an OpenSession call or AFPLogin call, the .XPP driver
  19514. sets the first two bytes of the session control block (SCB) to zero.  When the .XPP
  19515. driver receives an attention, the first two bytes of the SCB are set to the attention
  19516. bytes from the packet (which are always nonzero).
  19517.  
  19518. Note: A higher-level language such as Pascal may not wish to have a low-level
  19519.       attention routine called.  A Pascal program can poll the attention bytes,
  19520.       and if they are ever nonzero, the program will know that an attention
  19521.       has come in.  (It would then set the attention bytes back to zero.)
  19522.       Of course, two or more attentions could be received between successive
  19523.       polls, and only the last one would be recorded.
  19524.  
  19525. The .XPP driver also calls the attention routine when the session is closed by either
  19526. the server, workstation, or ASP itself (if the ASP session times out).  In these
  19527. cases, the attention bytes in the SCB are unchanged.
  19528.  
  19529. »The Attention Routine
  19530.  
  19531. The attention routine is called at interrupt level and must observe interrupt conventions.
  19532. Specifically, the interrupt routine can change registers A0 through A3 and D0 through
  19533. D3 and it must not make any Memory Manager calls.
  19534.  
  19535. It will be called with
  19536.  
  19537.   •  D0 (word) equal to the SessRefnum for that session (see OpenSession
  19538.      Function)
  19539.   •  D1 (word) equal to the attention bytes passed by the server (or zero
  19540.      if the session is closing)
  19541.  
  19542. Return with an RTS (return from subroutine) to resume normal execution.
  19543.  
  19544. The next section describes the calls that can be made to the .XPP driver.
  19545.  
  19546. _______________________________________________________________________________
  19547.  
  19548.  
  19549. æKY Calling…the….XPP…Driver
  19550. æC »CALLING THE .XPP DRIVER                                  AppleTalkManager
  19551. _______________________________________________________________________________
  19552.  
  19553. This section describes how to use the .XPP driver and how to call the .XPP driver
  19554. routines from assembly language and Pascal.
  19555.  
  19556. _______________________________________________________________________________
  19557.  
  19558. »Using XPP
  19559.  
  19560. The .XPP driver implements the workstation side of ASP and provides a mechanism for
  19561. the workstation to send AppleTalk Filing Protocol (AFP) commands to the server.
  19562.  
  19563. »Allocating Memory
  19564.  
  19565. Every call to the .XPP driver requires the caller to pass in whatever memory is
  19566. needed by the driver for the call, generally at the end of the queue element. When a
  19567. session is opened, the memory required for maintenance of that session
  19568. (that is, the Session Control Block) is also passed in.
  19569.  
  19570. For standard Device Manager calls, a queue element of a specific size equal to IOQElSize
  19571. is allocated.  When issuing many calls to XPP, it is the caller’s responsibility to
  19572. allocate a queue element that is large enough to accommodate the .XPP driver’s requirements
  19573. for executing that call, as defined below.  Once allocated, that memory can’t be
  19574. modified until the call completes.
  19575.  
  19576. »Opening the .XPP Driver
  19577.  
  19578. To open the .XPP driver, issue a Device Manager Open call.  (Refer to the Device
  19579. Manager chapter.)  The name of the .XPP driver is '.XPP'.  The original Macintosh
  19580. ROMs require that .XPP be opened only once. With new ROMs, the .XPP unit number can
  19581. always be obtained through an Open call.  With old ROMs only, the .XPP unit number
  19582. must be hard coded to XPPUnitNum (40) since only one Open call can be issued to the
  19583. driver.
  19584.  
  19585. The .XPP driver cannot be opened unless AppleTalk is open.  The application must
  19586. ensure that the .MPP and .ATP drivers are opened, as described earlier in this chapter.
  19587.  
  19588. The xppLoaded bit (bit 5) in the PortBUse byte in low memory indicates whether or not
  19589. the .XPP driver is open.
  19590.  
  19591. »Example
  19592.  
  19593. The following is an example of the procedure an application might use to open the
  19594. .XPP driver.
  19595.  
  19596. ;    Routine: OpenXPP
  19597. ;
  19598. ;        Open the .XPP driver and return the driver refNum for it.
  19599. ;
  19600. ;        Exit:    D0 = error code (ccr's set)
  19601. ;                 D1 = XPP driver refNum (if no errors)
  19602. ;
  19603. ;        All other registers preserved
  19604. ;
  19605. xppUnitNum    EQU    40                 ;default XPP driver number
  19606. xppTfRNum     EQU    -(xppUnitNum+1)    ;default XPP driver refNum
  19607.  
  19608. OpenXPP
  19609.     MOVE.L    A0-A1/D2,-(SP)            ;save registers
  19610.     MOVE      ROM85,D0                  ;check ROM type byte
  19611.     BPL.S     @10                       ;branch if >=128K ROMs
  19612.     BTST      #xppLoadedBit,PortBUse    ;is the XPP driver open already?
  19613.     BEQ.S     @10                       ;if not open, then branch to Open code
  19614.     MOVE      #xppTfRNum,D1             ;else use this as driver refnum
  19615.     MOVEQ     #0,D0                     ;set noErr
  19616.     BRA.S     @90                       ;and exit
  19617. ;
  19618. ; XPP driver not open. Make an _Open call to it. If using a 128K
  19619. ; ROM machine and the driver is already open, we will make another
  19620. ; Open call to it just so we get the correct driver refNum.
  19621. ;
  19622. @10 SUB       #ioQElSize,SP             ;allocate temporary param block
  19623.     MOVE.L    SP,A0                     ;A0 -> param block
  19624.     LEA       XPPName, A1               ;A1 -> XPP (ASP/AFP) driver name
  19625.     MOVE.L    A1,ioFileName(A0)         ;driver name into param block
  19626.     CLR.B     ioPermssn(A0)             ;clear permissions byte
  19627.     _Open
  19628.     MOVE      ioRefNum(A0),D1           ;D1=driver refNum (invalid if error)
  19629.     ADD       #ioQElSize,SP             ;deallocate temp param block
  19630. @90 MOVE.L    (SP)+,A0-A1/D2            ;restore registers
  19631.     TST       D0                        ;error? (set ccr's)
  19632.     RTS
  19633.     
  19634. XPPName  DC.B  4                        ;length of string
  19635.          DC.B  '.XPP'                   ;driver name
  19636.  
  19637. From Pascal, XPP can be opened through the OpenXPP call, which returns the driver’s
  19638. reference number:
  19639.  
  19640. FUNCTION OpenXPP (VAR xppRefnum: INTEGER) : OSErr;
  19641.  
  19642. »Open Errors
  19643.  
  19644. Errors returned when calling the Device Manager Open routine if the function does not
  19645. execute properly include the following:
  19646.  
  19647.   •  errors returned by System
  19648.   •  portInUse is returned if the AppleTalk port is in use by a driver
  19649.      other than AppleTalk or if AppleTalk is not open.
  19650.  
  19651. »Closing the .XPP Driver
  19652.  
  19653. To close the .XPP driver, call the Device Manager Close routine.
  19654.  
  19655. Warning:  There is generally no reason to close the driver.  Use this
  19656.           call sparingly, if at all.  This call should generally be used
  19657.           only by system-level applications.
  19658.  
  19659. »Close Errors
  19660.  
  19661. Errors returned when calling the Device Manager Close routine if the function does
  19662. not execute properly include the following:
  19663.  
  19664.   •  errors returned by System
  19665.   •  closeErr (new ROMs only) is returned if you try to close the driver
  19666.      and there are sessions active through that driver.  When sessions are
  19667.      active, closeErr is returned and the driver remains open.
  19668.   •  on old ROMs the driver is closed whether or not sessions are active
  19669.      and no error is returned. Results are unpredictable if sessions are
  19670.      still active.
  19671.  
  19672. »Session Control Block
  19673.  
  19674. The session control block (SCB) is a nonrelocatable block of data passed by the
  19675. caller to XPP upon session opening. XPP reserves this block for use in maintaining an
  19676. open session.   The SCB size is defined by the constant scbMemSize.  The SCB is a
  19677. locked block, and as long as the session is open, the SCB cannot be modified in any
  19678. way by the application.  There is one SCB for each open session. This block can be
  19679. reused once a CloseSess call is issued and completed for that session or when the
  19680. session is indicated as closed.
  19681.  
  19682. _______________________________________________________________________________
  19683.  
  19684. »How to Access the .XPP Driver
  19685.  
  19686. This section contains information for programmers using Pascal and assembly-language
  19687. routines.
  19688.  
  19689. All .XPP driver routines can be executed either synchronously (meaning that the
  19690. application can’t continue until the routine is completed) or asynchronously
  19691. (meaning that the application is free to perform other tasks while the routine is
  19692. executing).
  19693.  
  19694. XPP calls are made from Pascal in the same manner as MPP and ATP calls, with the
  19695. exception that when making XPP calls the caller must set the XPP driver’s refnum.  
  19696. This refnum is returned in the XPPOpen call’s parameter block.
  19697.  
  19698. A Pascal variant record has been defined for all XPP calls.  This parameter block is
  19699. detailed in the “.XPP Driver Parameter Block Record” section below.  The first four
  19700. fields (which are the same for all calls) are automatically filled in by the device
  19701. manager.  The csCode field is automatically filled in by Pascal, depending on which
  19702. call is being made.  The caller must, however, set the ioRefnum field to XPP’s reference
  19703. number, as returned in the OpenXPP call.  The ioVRefnum field is unused.
  19704.  
  19705. Note that the parameter block is defined so as to be the maximum size used by any
  19706. call.  Different calls take different size parameter blocks, each call requiring a
  19707. certain minimum size.  Callers are free to abbreviate the parameter block where
  19708. appropriate.
  19709.  
  19710. »General
  19711.  
  19712. With each routine, a list of the parameter block fields used by the call is also
  19713. given.  All routines are invoked by Device Manager Control calls with the csCode
  19714. field equal to the code corresponding to the function being called.  The number next
  19715. to each field name indicates the byte offset of the field from the start of the
  19716. parameter block pointed to by A0; only assembly-language programmers need to be
  19717. concerned with it.  An arrow next to each parameter name indicates whether it’s an
  19718. input, output, or input/output parameter:
  19719.  
  19720. Arrow    Meaning
  19721.   <--    Parameter is passed
  19722.   <--    Parameter is returned
  19723.   <->    Parameter is passed and returned
  19724.  
  19725. All Device Manager Control calls return an integer result code in the ioResult field.
  19726.  Each routine description lists all the applicable result codes, along with a short
  19727. description of what the result code means.  Refer to the section
  19728. “XPP Driver Result Codes” for an alphabetical list of result codes returned by the
  19729. .XPP driver.
  19730.  
  19731. Each routine description includes a Pascal form of the call.   Pascal calls to the
  19732. .XPP Driver are of the form:
  19733.  
  19734. FUNCTION XPPCall (paramBlock: XPPParmBlkPtr,async: BOOLEAN) : OSErr;
  19735.  
  19736. XPPCall is the name of the routine.
  19737.  
  19738. The parameter paramBlock points to the actual I/O queue element used in the
  19739. _Control call, filled in by the caller with the parameters of the routine.
  19740.  
  19741. The parameter async indicates whether or not the call should be made asynchronously. 
  19742.  If async is TRUE, the call is executed asynchronously; otherwise the call is executed
  19743. synchronously.
  19744.  
  19745. The routine returns a result code of type OSErr.
  19746.  
  19747. ».XPP Driver Parameter Block Record
  19748.  
  19749. XPPParamBlock = PACKED RECORD
  19750.     qLink:         QElemPtr;  {next queue entry}
  19751.     qType:         INTEGER;   {queue type}
  19752.     ioTrap:        INTEGER;   {routine trap}
  19753.     ioCmdAddr:     Ptr;       {routine address}
  19754.     ioCompletion:  ProcPtr;   {completion routine}
  19755.     ioResult:      OSErr;     {result code}
  19756.     cmdResult:     LONGINT;   {command result (ATP user bytes) [long]}
  19757.     ioVRefNum:     INTEGER;   {volume reference or drive number)
  19758.     ioRefNum:      INTEGER;   {driver reference number)
  19759.     csCode:        INTEGER;   {Call command code}
  19760.     CASE XPPPrmBlkType OF
  19761.       ASPAbortPrm:
  19762.         (abortSCBPtr:    Ptr);      {SCB pointer for AbortOS [long]}
  19763.       ASPSizeBlk:
  19764.         (aspMaxCmdSize:  INTEGER;   {for SPGetParms [word]
  19765.         aspQuantumSize:  INTEGER;   {for SPGetParms [word]}
  19766.         numSesss:        INTEGER);  {for SPGetParms [word]}
  19767.       XPPPrmBlk:
  19768.         (sessRefnum:     INTEGER;   {offset to session refnum [word]}
  19769.         aspTimeout:      Byte;      {timeout for ATP [byte]}
  19770.         aspRetry:        Byte;      {retry count for ATP [byte]}
  19771.         CASE XPPSubPrmType OF
  19772.           ASPOpenPrm:
  19773.             (serverAddr:    AddrBlock;  {server address block [longword]}
  19774.             scbPointer:     Ptr;        {SCB pointer [longword]}
  19775.             attnRoutine:    Ptr);       {attention routine pointer [long]}
  19776.           ASPSubPrm:
  19777.             (cbSize:        INTEGER;    {command block size [word]}
  19778.             cbPtr:          Ptr;        {command block pointer [long]}
  19779.             rbSize:         INTEGER;    {reply buffer size [word]}
  19780.             rbPtr:          Ptr;        {reply buffer pointer [long]}
  19781.             CASE XPPEndPrmType OF
  19782.               AFPLoginPrm:
  19783.                 (afpAddrBlock:     AddrBlock;    {address block in}
  19784.                                                  { AFPlogin [long]}
  19785.                 afpSCBPtr:         Ptr;          {SCB pointer in }
  19786.                                                  { AFPlogin [long]}
  19787.                 afpAttnRoutine:    Ptr);         {attn routine pointer }
  19788.                                                  { in AFPlogin}
  19789.               ASPEndPrm:
  19790.                 (wdSize:           INTEGER;      {write data size [word]}
  19791.                 wdPtr:             Ptr;          {write data pointer [long]}
  19792.                 ccbStart:          ARRAY[0..295] OF Byte)));   {CCB memory }
  19793.                                                                { for driver}
  19794.      {Write max size(CCB) = 296; all other calls = 150}
  19795.      END;
  19796.  
  19797. _______________________________________________________________________________
  19798.  
  19799. »AppleTalk Session Protocol Functions
  19800.  
  19801. This section contains descriptions of the .XPP driver functions that you can call. 
  19802. Each function description shows the required parameter block fields, their offsets
  19803. within the parameter block and a brief definition of the field.  Possible result
  19804. codes are also described.
  19805.  
  19806. »Note on Result Codes
  19807.  
  19808. An important distinction exists between the aspParamErr and aspSessClose  result
  19809. codes that may be returned by the .XPP driver.
  19810.  
  19811. When the driver returns aspParamErr to a call that takes as an input a session reference
  19812. number, the session reference number does not relate to a valid open session.  There
  19813. could be several reasons for this, such as the workstation or server end closed the
  19814. session or the server end of the session died.
  19815.  
  19816. The aspSessClosed result code indicates that even though the session reference number
  19817. relates to a valid session, that particular session is in the process of closing down
  19818. (although  the session is not yet closed).
  19819.  
  19820. FUNCTION ASPOpenSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19821.  
  19822. Parameter block
  19823.   -->    26    csCode       word       Always ASPOpenSess
  19824.   -->    28    sessRefnum   word       Session reference number
  19825.   -->    30    aspTimeout   byte       Retry interval in seconds
  19826.   -->    31    aspRetry     byte       Number of retries
  19827.   -->    32    serverAddr   long word  Server socket address
  19828.   -->    36    scbPointer   pointer    Pointer to session control block
  19829.   -->    40    attnRoutine  pointer    Pointer to attention routine
  19830.  
  19831. ASPOpenSession initiates (opens) a session between the workstation and a server.  The
  19832. required parameter block is shown above.  A brief definition of the fields follows.
  19833.  
  19834. SessRefnum is a unique number identifying the open session between the workstation
  19835. and the server.  The SessRefnum is returned when the function completes successfully
  19836. and is used in all calls to identify the session.
  19837.  
  19838. ASPTimeOut is the interval in seconds between retries of the open session request.
  19839.  
  19840. ASPRetry is the number of retries that will be attempted.
  19841.  
  19842. ServerAddr is the network identifier or address of the socket on which the server is
  19843. listening.
  19844.  
  19845. SCBPointer points to a nonrelocatable block of data for the session control block
  19846. (SCB) that the .XPP driver reserves for use in maintaining an open session.   The SCB
  19847. size is defined by the constant scbMemSize.  The SCB is a locked block and as long as
  19848. the session is open, the SCB cannot be modified in any way by the application.  There
  19849. is one SCB for each open session.  This block can be reused when a CloseSess call is
  19850. issued and completed for that session, or when the session is indicated as closed
  19851. through return of aspParamErr as the result of a call for that session.
  19852.  
  19853. AttnRoutine is a pointer to a routine that is invoked if an attention from the server
  19854. is received, or upon session closing.  If this pointer is equal to zero, no attention
  19855. routine will be invoked.
  19856.  
  19857. Result codes    aspNoMoreSess    Driver cannot support another session
  19858.                 aspParamErr      Server returned bad (positive) error code    
  19859.                 aspNoServers     No servers at that address, or the server
  19860.                                  did not respond to the request
  19861.                 reqAborted       OpenSess was aborted by an AbortOS
  19862.                 aspBadVersNum    Server cannot support the offered 
  19863.                                  version number
  19864.                 aspServerBusy    Server cannot open another session
  19865.  
  19866. Note: The number of sessions that the driver is capable of supporting
  19867.       depends on the machine that the driver is running on. 
  19868.  
  19869. FUNCTION ASPCloseSession (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19870.  
  19871. Parameter block
  19872.   -->    26    csCode      word  Always ASPCloseSession
  19873.   -->    28    sessRefnum  word  Session reference number
  19874.  
  19875. ASPCloseSession closes the session identified by the sessRefnum returned in the
  19876. ASPOpenSession call.  ASPCloseSession aborts any calls that are active on the session,
  19877. closes the session, and calls the attention routine, if any, with an attention code
  19878. of zero (zero is invalid as a real attention code).
  19879.  
  19880. Result codes    aspParamErr      Parameter error, indicates an invalid
  19881.                                  session reference number
  19882.                 aspSessClosed    Session already in process of closing
  19883.  
  19884. FUNCTION ASPAbortOS (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19885.  
  19886. Parameter block
  19887.   -->    26    csCode            word     Always ASPAbortOS
  19888.   -->    28    abortSCBPointer   pointer  Pointer to session control block
  19889.  
  19890. ASPAbortOS aborts a pending (not yet completed) ASPOpenSession call.  The aborted
  19891. ASPOpenSession call will return a reqAborted error.
  19892.  
  19893. AbortSCBPointer points to the original SCB used in the the pending ASPOpenSession
  19894. call.
  19895.  
  19896. Result codes    cbNotFound    SCB not found, no outstanding open session
  19897.                               to be aborted.
  19898.                               Pointer did not point to an open session SCB.
  19899.  
  19900. FUNCTION ASPGetParms (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  19901.  
  19902. Parameter block
  19903.   -->    26    csCode          word  Always ASPGetParms
  19904.   -->    28    aspMaxCmdSize   word  Maximum size of command block
  19905.   -->    30    aspQuantumSize  word  Maximum data size
  19906.   -->    32    numSesss        word  Number of sessions
  19907.  
  19908. ASPGetParms returns three ASP parameters.  This call does not require an open session.
  19909.  
  19910. ASPMaxCmdSize is the maximum size of a command that can be sent to the server.
  19911.  
  19912. ASPQuantumSize is the maximum size of data that can be transferred to the server in a
  19913. Write request or from the server in a command reply.
  19914.  
  19915. NumSess is the number of concurrent sessions supported by the driver.
  19916.  
  19917. FUNCTION ASPCloseAll (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19918.  
  19919. Parameter block
  19920.   -->    26    csCode  word  Always ASPCloseAll
  19921.  
  19922. ASPCloseAll closes every session that the driver has active, aborting all active
  19923. requests and invoking the attention routines where provided.  This call should be
  19924. used carefully.  ASPCloseAll can be used as a system level resource for making sure
  19925. all sessions are closed prior to closing the driver.
  19926.  
  19927. FUNCTION ASPUserWrite (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  19928.  
  19929. Parameter block
  19930.   -->    18    cmdResult   long word  ASP command result
  19931.   -->    26    csCode      word       Always UserWrite
  19932.   -->    28    sessRefnum  word       Session reference number
  19933.   -->    30    aspTimeout  byte       Retry interval in seconds
  19934.   -->    32    cbSize      word       Command block size
  19935.   -->    34    cbPtr       pointer    Command block pointer
  19936.   <->    38    rbSize      word       Reply buffer size and reply size
  19937.   -->    40    rbPtr       pointer    Reply buffer pointer
  19938.   <->    44    wdSize      word       Write data size
  19939.   -->    46    wdPtr       pointer    Write data pointer
  19940.   -->    50    ccbStart    record     Start of memory for CCB
  19941.  
  19942. ASPUserWrite transfers data on a session.  ASPUserWrite is one of the two main calls
  19943. that can be used to transfer data on an ASP session.  The other call that performs a
  19944. similar data transfer  is ASPUserCommand described below.  The ASPUserWrite command
  19945. returns data in two different places.  Four bytes of data are returned in the cmdResult
  19946. field and a variable size reply buffer is also returned.
  19947.  
  19948. CmdResult is four bytes of data returned by the server.
  19949.  
  19950. SessRefnum is the session reference number returned in the ASPOpenSession call.
  19951.  
  19952. ASPTimeOut is the interval in seconds between retries of the call.  Notice that there
  19953. is no aspRetry field (retries are infinite).  The command will be retried at the
  19954. prescribed interval until completion or the session is closed.
  19955.  
  19956. CBSize is the size in bytes of the command data that is to be written on the session.
  19957.  The size of the command block must not exceed the value of aspMaxCmdSize returned by
  19958. the ASPGetParms call. Note that this buffer is not the data to be written by the
  19959. command but only the data of the command itself.
  19960.  
  19961. CBPtr points to the command data.
  19962.  
  19963. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  19964. command.  RBSize is also returned and indicates the size of the reply that was actually
  19965. returned.
  19966.  
  19967. RBPtr points to the reply buffer.
  19968.  
  19969. WDSize is passed and indicates the size of the write data in bytes to be sent by the
  19970. command.  WDSize is also returned and indicates the size of the write data that was
  19971. actually written.
  19972.  
  19973. WDPointer points to the write data buffer.
  19974.  
  19975. CCBStart is the start of the memory to be used by the .XPP driver for the command
  19976. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  19977. the exact requirement, refer to the CCB Sizes section of this document.
  19978.  
  19979. Result codes     aspParamErr       Invalid session number, session has
  19980.                                    been closed
  19981.                  aspSizeErr        Command block size is bigger than MaxCmdSize
  19982.                  aspSessClosed     Session is closing
  19983.                  aspBufTooSmall    Reply is bigger than response buffer;
  19984.                                    the buffer will be filled, data will
  19985.                                    be truncated
  19986.  
  19987. FUNCTION ASPUserCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  19988.  
  19989. Parameter block
  19990.   -->    18    cmdResult   long word  ASP command result
  19991.   -->    26    csCode      word       Always ASPUserCommand
  19992.   -->    28    sessRefnum  word       Session number
  19993.   -->    30    aspTimeout  byte       Retry interval in seconds
  19994.   -->    32    cbSize      word       Command block size
  19995.   -->    34    cbPtr       pointer    Command block pointer
  19996.   <->    38    rbSize      word       Reply buffer and reply size
  19997.   -->    40    rbPtr       pointer    Reply buffer pointer
  19998.   -->    50    ccbStart    record     Start of memory for CCB
  19999.  
  20000. ASPUserCommand is used to send a command to the server on a session.
  20001.  
  20002. SessRefnum is the session reference number returned in the ASPOpenSession call.
  20003.  
  20004. ASPTimeOut is the interval in seconds between retries of the call.  Notice that there
  20005. is no aspRetry field (retries are infinite).  The command will be retried at the
  20006. prescribed interval until completion or the session is closed.
  20007.  
  20008. CBSize is the size in bytes of the block of data that contains the command to be sent
  20009. to the server on the session.  The size of the command block must not exceed the
  20010. value of aspMaxCmdSize returned by the ASPGetParms call.
  20011.  
  20012. CBPointer points to the block of data containing the command that is to be sent to
  20013. the server on the session.
  20014.  
  20015. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20016. command.  RBSize is also returned and indicates the size of the reply that was actually
  20017. returned.
  20018.  
  20019. RBPtr points to the reply buffer.
  20020.  
  20021. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20022. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20023. the exact requirement refer to the CCB Sizes section of this document.
  20024.  
  20025. Result codes     aspParamErr       Invalid session number, session has
  20026.                                    been closed
  20027.                  aspSizeErr        Command block size is bigger than MaxCmdSize
  20028.                  aspSessClosed     Session is closing
  20029.                  aspBufTooSmall    Reply is bigger than response buffer;
  20030.                                    the buffer will be filled, data will
  20031.                                    be truncated
  20032.  
  20033. FUNCTION ASPGetStatus (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20034.  
  20035. Parameter block
  20036.   -->    26    csCode      word       Always ASPGetStatus
  20037.   -->    30    aspTimeout  byte       Retry interval in seconds
  20038.   -->    31    aspRetry    byte       Number of retries
  20039.   -->    32    serverAddr  long word  Server socket address
  20040.   <->    38    rbSize      word       Reply buffer and reply size
  20041.   -->    40    rbPtr       pointer    Reply buffer pointer
  20042.   -->    50    ccbStart    record     Start of memory for CCB
  20043.  
  20044. ASPGetStatus returns server status.  This call is also used as GetServerInfo at the
  20045. AFP level. This call is unique in that it transfers data over the network without
  20046. having a session open.  This call does not pass any data but requests that server
  20047. status be returned.
  20048.  
  20049. ASPTimeOut is the interval in seconds between retries of the call.
  20050.  
  20051. ASPRetry is the number of retries that will be attempted.
  20052.  
  20053. ServerAddr is the network identifier or address of the socket on which the server is
  20054. listening.
  20055.  
  20056. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20057. command. RBSize is also returned and indicates the size of the reply that was actually
  20058. returned.
  20059.  
  20060. RBPtr points to the reply buffer.
  20061.  
  20062. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20063. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20064. the exact requirement refer to the CCB Sizes section of this document.
  20065.  
  20066. Result codes    aspBufTooSmall    Reply is bigger than response buffer,
  20067.                                   or Replysize is bigger than ReplyBuffsize
  20068.                 aspNoServer       No response from server at address used
  20069.                                   in call
  20070.  
  20071. _______________________________________________________________________________
  20072.  
  20073. »AFP Implementation
  20074.  
  20075. The AFPCall function (called AFPCommand in Pascal) passes a command to an AFP server.
  20076.  The first byte of the AFPCall command buffer (the AFP command byte) must contain a
  20077. valid AFP command code.
  20078.  
  20079. Note:  Server information should be gotten through an ASPGetStatus call
  20080.        (described above).  ASPGetStatus is equivalent to the AFPGetSrvrInfo.
  20081.        Making an AFP GetSrvrInfo call using AFPCommand results in an error.
  20082.  
  20083. »Mapping AFP Commands
  20084.  
  20085. Most AFP calls are implemented by XPP through a very simple one-to-one mapping of an
  20086. AFP call to an ASP call without interpretation or verification of the data.
  20087.  
  20088. The .XPP driver maps AFP command codes to ASP commands according to the following
  20089. conventions:
  20090.  
  20091.   AFP Command Code     Comment
  20092.  
  20093.   $00                  Invalid AFP command
  20094.   $01–$BE (1–190)      Mapped to UserCommand  (with the exceptions
  20095.                        listed below)
  20096.   $BF (191)            Mapped to UserCommand  (Reserved for developers;
  20097.                        will never be used by Apple)
  20098.   $C0–$FD (192–253)    Mapped to UserWrite
  20099.   $FE (254)            Mapped to UserWrite  (will never be used by Apple)
  20100.   $FF (255)            Invalid AFP command
  20101.  
  20102. The following AFP calls are exceptions to the above conventions:
  20103.  
  20104.   AFP Command (Code/Decimal)  Comment
  20105.  
  20106.   getSrvrInfo (15)            Mapped to ASPGetStatus  (Use ASPGetStatus
  20107.                               to make this call)
  20108.   login (18)                  Mapped to appropriate log-in dialog including
  20109.                               ASPOpenSession call
  20110.   loginCont (19)              Mapped to appropriate log-in dialog
  20111.   logout (20)                 Mapped to ASPCloseSession
  20112.   write (33)                  Mapped to ASPUserWrite
  20113.  
  20114. The following AFP calls can pass or return more data than can fit in quantumSize
  20115. bytes (eight ATP response packets) and may be broken up by XPP into multiple ASP
  20116. calls.
  20117.  
  20118.   AFP Command (Code/Decimal)  Comment
  20119.  
  20120.   read (27)                   Can return up to the number of bytes
  20121.                               indicated in reqCount
  20122.   write (33)                  Can pass up to the number of bytes
  20123.                               indicated in reqCount
  20124.  
  20125. »AFPCall Function
  20126.  
  20127. The AFPCall function can have one of the following command formats.
  20128.  
  20129.   •  General
  20130.   •  Login
  20131.   •  AFPWrite
  20132.   •  AFPRead
  20133.  
  20134. »General Command Format
  20135.  
  20136. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20137.  
  20138. Parameter block
  20139.   -->    18    cmdResult   long word  AFP command result
  20140.   -->    26    csCode      word       Always AFPCall
  20141.   -->    28    sessRefnum  word       Session reference number
  20142.   -->    30    aspTimeout  byte       Retry interval in seconds
  20143.   -->    32    cbSize      word       Command buffer size
  20144.   -->    34    cbPtr       pointer    Command buffer
  20145.   <->    38    rbSize      word       Reply buffer size and reply size
  20146.   -->    40    rbPtr       pointer    Reply buffer pointer
  20147.   <->    44    wdSize      word       Write data size
  20148.   -->    46    wdPtr       pointer    Write data pointer
  20149.   -->    50    ccbStart    record     Start of memory for CCB
  20150.  
  20151. The general command format for the AFPCall function passes an AFP command to the
  20152. server.  This format is used for all AFP calls except AFPLogin, AFPRead, and AFPWrite.
  20153.   Note that from Pascal this call is referred to as AFPCommand.
  20154.  
  20155. CmdResult is four bytes of data returned from the server containing an indication of
  20156. the result of the AFP command.
  20157.  
  20158. SessRefnum is the session reference number returned in the AFPLogin call.
  20159.  
  20160. ASPTimeOut is the interval in seconds between retries of the call by the driver.
  20161.  
  20162. CBSize is the size in bytes of the block of data that contains the command to be sent
  20163. to the server on the session. The size of the command block must not exceed the value
  20164. of aspMaxCmdSize returned by the ASPGetParms call.
  20165.  
  20166. CBPtr points to start of the block of data (command block) containing the command
  20167. that is to be sent to the server on the session.  The first byte of the command block
  20168. must contain the AFP command byte.  Subsequent bytes in the command buffer contain
  20169. the  parameters associated with the command as defined in the AFP document.
  20170.  
  20171. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20172. command. RBSize is also returned and indicates the size of the reply that was actually
  20173. returned.
  20174.  
  20175. RBPtr points to the reply buffer.
  20176.  
  20177. WDSize is the size of data to be written to the server (only used if the command is
  20178. one that is mapped to an ASPUserWrite).
  20179.  
  20180. WDPtr points to the write data buffer (only used if the command is one that is mapped
  20181. to an ASPUserWrite).
  20182.  
  20183. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20184. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  20185. the exact requirement refer to the CCB Sizes section of this document.
  20186.  
  20187. Result codes    aspParamErr       Invalid session number; session has
  20188.                                   been closed
  20189.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  20190.                 aspSessClosed     Session is closing
  20191.                 aspBufTooSmall    Reply is bigger than response buffer or
  20192.                                   buffer will be filled, data will be truncated
  20193.                 afpParmError      AFP command block size is equal to zero.
  20194.                                   This error will also be returned if the
  20195.                                   command byte in the command block is equal
  20196.                                   to 0 or $FF (255) or GetSrvrStatus (15).
  20197.  
  20198. »Login Command Format
  20199.  
  20200. The AFP login command executes a series of AFP operations as defined in the AFP Draft
  20201. Proposal.  For further information, refer to the AFP document.
  20202.  
  20203. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN): OSErr;
  20204.  
  20205. Parameter block
  20206.   -->    18    cmdResult       long word  AFP command result
  20207.   -->    26    csCode          word       Always AFPCall
  20208.   -->    28    sessRefnum      word       Session reference number
  20209.   -->    30    aspTimeout      byte       Retry interval in seconds
  20210.   -->    31    aspRetry        byte       Number of retries
  20211.   -->    32    cbSize          word       Command buffer size
  20212.   -->    34    cbPtr           pointer    Command buffer
  20213.   <->    38    rbSize          word       Reply buffer size and reply size
  20214.   -->    40    rbPtr           pointer    Reply buffer pointer
  20215.   -->    44    afpAddrBlock    long word  Server address block
  20216.   <->    48    afpSCBPtr       pointer    SCB pointer
  20217.   <->    52    afpAttnRoutine  pointer    Attention routine pointer
  20218.   -->    50    ccbStart        record     Start of command control block
  20219.  
  20220. CmdResult is four bytes of data returned from the server containing an indication of
  20221. the result of the AFP command.
  20222.  
  20223. SessRefnum is the session reference number (returned by the AFPLogin call).
  20224.  
  20225. ASPTimeOut is the interval in seconds between retries of the call.
  20226.  
  20227. ASPRetry is the number of retries that will be attempted.
  20228.  
  20229. CBSize is the size in bytes of the block data that contains the command to be sent to
  20230. the server on the session. The size of the command block must not exceed the value of
  20231. aspMaxCmdSize returned by the ASPGetParms call.
  20232.  
  20233. CBPtr points to the block of data (command block) containing the AFP login command
  20234. that is to be sent to the server on the session.  The first byte of the command block
  20235. must be the AFP login command byte.  Subsequent bytes in the command buffer contain
  20236. the parameters associated with the command.
  20237.  
  20238. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20239. command.  RBSize is also returned and indicates the size of the reply that was actually
  20240. returned.
  20241.  
  20242. RBPtr points to the reply buffer.
  20243.  
  20244. AFPServerAddr is the network identifier or address of the socket on which the server
  20245. is listening.
  20246.  
  20247. AFPSCBPointer points to a locked block of data for the session control block
  20248. (SCB). The SCB size is defined by scbMemSize.  The SCB is a locked block, and as long
  20249. as the session is open, the SCB cannot be modified in any way by the application. 
  20250. There is one SCB for each open session.
  20251.  
  20252. AFPAttnRoutine is a pointer to a routine that is invoked if an attention from the
  20253. server is received.  When afpAttnRoutine is equal to zero, no attention routine will
  20254. be invoked.
  20255.  
  20256. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20257. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20258. the exact requirement refer to the CCB Sizes section later in this chapter.
  20259.  
  20260. Note:  In the parameter block, the afpSCBPointer and the afpAttnRoutine
  20261.        fields overlap with the start of the CCB and are modified by the call.
  20262.  
  20263. Result codes    aspSizeErr        Command block size is bigger than MaxCmdSize
  20264.                 aspBufTooSmall    Reply is bigger than response buffer or
  20265.                                   buffer will be filled, data will be truncated
  20266.                 aspNoServer       Server not responding
  20267.                 aspServerBusy     Server cannot open another session
  20268.                 aspBadVersNum     Server cannot support the offered ASP
  20269.                                   version number
  20270.                 aspNoMoreSess     Driver cannot support another session.
  20271.  
  20272. »AFPWrite Command Format
  20273.  
  20274. The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
  20275. calls that read or write a data block that is larger than a single ASP-level call is
  20276. capable of reading or writing.  The maximum number of bytes of data that can be read
  20277. or written at the ASP level is equal to quantumSize.
  20278.  
  20279. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20280.  
  20281. Parameter block
  20282.   -->    18    cmdResult   long word  AFP command result
  20283.   -->    26    csCode      word       Always AFPCall
  20284.   -->    28    sessRefnum  word       Session number
  20285.   -->    30    aspTimeout  byte       Retry interval in seconds
  20286.   -->    32    cbSize      word       Command buffer size
  20287.   -->    34    cbPtr       pointer    Command buffer
  20288.   <->    38    rbSize      word       Reply buffer size and reply size
  20289.   -->    40    rbPtr       pointer    Reply buffer pointer
  20290.   -->    44    wdSize      word       (used internally)
  20291.   <->    46    wdPtr       pointer    Write data pointer  (updated)
  20292.   -->    50    ccbStart    record     Start of memory for CCB
  20293.  
  20294. CmdResult is four bytes of data returned from the server containing an indication of
  20295. the result of the AFP command.
  20296.  
  20297. SessRefnum is the session reference number returned in the AFPLogin call.
  20298.  
  20299. ASPTimeOut is the interval in seconds between retries of the call.
  20300.  
  20301. CBSize is the size in bytes of the block data that contains the command to be sent to
  20302. the server on the session.  The size of the command block must not exceed the value
  20303. of aspMaxCmdSize returned by the aspGetParms call.
  20304.  
  20305. CBPtr points to the block of data (see command block structure below) containing the
  20306. AFP write command that is to be sent to the server on the session.  The first byte of
  20307. the Command Block must contain the AFP write command byte.
  20308.  
  20309. RBSize is passed and indicates the size of the reply buffer in bytes expected by the
  20310. command.  RBSize is also returned and indicates the size of the reply that was actually
  20311. returned.
  20312.  
  20313. RBPtr points to the reply buffer.
  20314.  
  20315. WDSize is used internally.
  20316.  
  20317. Note:  This command does not pass the write data size in the queue element
  20318.        but in the command buffer.  XPP will look for the size in that buffer.
  20319.  
  20320. WDPtr is a pointer to the block of data to be written.  Note that this field will be
  20321. updated by XPP as it proceeds and will always point to that section of the data which
  20322. XPP is currently writing.
  20323.  
  20324. CCBStart is the start of the memory to be used by the XPP driver for the command
  20325. control block.  The size of this block is equal to a maximum of 296 bytes.  To determine
  20326. the exact requirement refer to the CCB Sizes section later in this chapter.
  20327.  
  20328. Command Block Structure:  The AFP write command passes several arguments to XPP in
  20329. the command buffer itself. The byte offsets are relative to the location pointed to
  20330. by cbPtr.
  20331.  
  20332.   -->    0    cmdByte       byte       AFP call command byte
  20333.   -->    1    startEndFlag  byte       Start/end Flag
  20334.   <->    4    rwOffset      long word  Offset within fork to write
  20335.   <->    8    reqCount      long word  Requested count
  20336.  
  20337. CmdByte is the AFP call command byte and must contain the AFP write command code.
  20338.  
  20339. StartEndFlag is a one-bit flag (the high bit of the byte) indicating whether the
  20340. rwOffset field is relative to the beginning or the end of the fork (all other bits
  20341. are zero).
  20342.  
  20343.   0 = relative to the beginning of the fork
  20344.   1 = relative to the end of the fork
  20345.  
  20346. RWOffset is the byte offset within the fork at which the write is to begin.
  20347.  
  20348. ReqCount indicates the size of the data to be written and is returned as the actual
  20349. size written.
  20350.  
  20351. The rwOffset and reqCount fields are modified by XPP as the write proceeds and will
  20352. always indicate the current value of these fields.
  20353.  
  20354. The Pascal structure of the AFP command buffer follows:
  20355.  
  20356. AFPCommandBlock = PACKED RECORD
  20357.                     cmdByte:       Byte;
  20358.                     startEndFlag:  Byte;
  20359.                     forkRefNum:    INTEGER;    {used by server}
  20360.                     rwOffset:      LONGINT;
  20361.                     reqCount:      LONGINT;
  20362.                     newLineFlag:   Byte;       {unused by write}
  20363.                     newLineChar:   CHAR;       {unused by write}
  20364.                   END;
  20365.  
  20366. Result codes    aspParamErr       Invalid session number
  20367.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  20368.                 aspSessClosed     Session is closing
  20369.                 aspBufTooSmall    Reply is bigger than response buffer
  20370.  
  20371. »AFPRead Command Format
  20372.  
  20373. The AFPWrite and AFPRead command formats allow the calling application to make AFP-level
  20374. calls that read or write a data block that is larger than a single ASP-level call is
  20375. capable of reading or writing.  The maximum number of bytes of data that can be read
  20376. or written at the ASP level is equal to quantumSize.
  20377.  
  20378. FUNCTION AFPCommand (xParamBlock: XPPParmBlkPtr; async: BOOLEAN) : OSErr;
  20379.  
  20380. Parameter block
  20381.   -->    18    cmdResult   long word  ASP command result
  20382.   -->    26    csCode      word       Always AFPCall
  20383.   -->    28    sessRefnum  word       Session number
  20384.   -->    30    aspTimeout  byte       Retry interval in seconds
  20385.   -->    32    cbSize      word       Command buffer size
  20386.   -->    34    cbPtr       pointer    Command buffer
  20387.   -->    38    rbSize      word       Used internally
  20388.   <->    40    rbPtr       pointer    Reply buffer pointer (updated)
  20389.   -->    50    ccbStart    record     Start of memory for CCB
  20390.  
  20391. CmdResult is four bytes of data returned from the server containing an indication of
  20392. the result of the AFP command.
  20393.  
  20394. SessRefnum is the session reference number returned in the AFPLogin  call.
  20395.  
  20396. ASPTimeOut is the interval in seconds between retries of the call.
  20397.  
  20398. CBSize is the size in bytes of the block data that contains the command to be sent to
  20399. the server on the session.  The size of the command block must not exceed the value
  20400. of aspMaxCmdSize returned by the GetParms call.
  20401.  
  20402. CBPtr points to the block of data (command block) containing the AFP read command
  20403. that is to be sent to the server on the session.  The first byte of the command block
  20404. must contain the AFP read command byte.  The command block structure is shown below.
  20405.  
  20406. RBSize  is used internally.
  20407.  
  20408. Note:  This command does not pass the read size in the queue element but
  20409.        in the command buffer.  XPP will look for the size in that buffer.
  20410.  
  20411. RBPtr points to the reply buffer.  Note that this field will be updated by XPP as it
  20412. proceeds and will always point to that section of the buffer that XPP is currently
  20413. reading into.
  20414.  
  20415. CCBStart is the start of the memory to be used by the .XPP driver for the command
  20416. control block.  The size of this block is equal to a maximum of 150 bytes.  To determine
  20417. the exact requirement refer to The CCB Sizes section later in this chapter.
  20418.  
  20419. Command Block Structure:  The AFP read command passes several arguments to XPP in the
  20420. command buffer itself. The byte offsets are relative to the location pointed to by
  20421. cbPointer.
  20422.  
  20423.   -->    0    cmdByte      byte       AFP call command byte
  20424.   <->    4    rwOffset     long word  Offset within fork to read
  20425.   <->    8    reqCount     long word  Requested count
  20426.   -->    12   newLineFlag  byte       Newline Flag
  20427.   -->    13   newLineChar  byte       Newline Character
  20428.  
  20429. CmdByte is the AFP call command byte and must contain the AFP read command code.
  20430.  
  20431. RWOffset is the byte offset within the fork at which the read is to begin.
  20432.  
  20433. ReqCount  indicates the size of the read data buffer and is returned as the actual
  20434. size read.
  20435.  
  20436. The rwOffset and reqCount fields are modified by XPP as the read proceeds and will
  20437. always indicate the current value of these fields.
  20438.  
  20439. NewLineFlag is a one-bit flag (the high bit of the byte) indicating whether or not
  20440. the read is to terminate at a specified character (all other bits are zero).
  20441.  
  20442.   0 = no Newline Character is specified
  20443.   1 = a Newline Character is specified
  20444.  
  20445. NewLineChar is any character from $00 to $FF (inclusive) that, when encountered in
  20446. reading the fork, causes the read operation to terminate.
  20447.  
  20448. The Pascal structure of the AFPCommand follows:
  20449.  
  20450. AFPCommandBlock = PACKED RECORD
  20451.                     cmdByte:       Byte;
  20452.                     startEndFlag:  Byte;     {unused for read}
  20453.                     forkRefNum:    INTEGER;  {used by server}
  20454.                     rwOffset:      LONGINT;
  20455.                     reqCount:      LONGINT;
  20456.                     newLineFlag:   Byte;
  20457.                     newLineChar:   CHAR;
  20458.                   END;
  20459.  
  20460. Result codes    aspParamErr       Invalid session number
  20461.                 aspSizeErr        Command block size is bigger than MaxCmdSize
  20462.                 aspSessClosed     Session is closing
  20463.                 aspBufTooSmall    Reply is bigger than response buffer
  20464.  
  20465. _______________________________________________________________________________
  20466.  
  20467. »CCB Sizes
  20468.  
  20469. The .XPP driver uses the memory provided at the end of the UserWrite, UserCommand,
  20470. and GetStatus functions parameter blocks as an internal command control block (CCB).
  20471. Using the maximum block sizes specified in the call descriptions will provide adequate
  20472. space for the call to execute successfully. However, this section is provided for
  20473. developers who wish to minimize the amount of memory taken up by the CCB in the queue
  20474. element.
  20475.  
  20476. Specifically, this memory is used for building data structures to be used in making
  20477. calls to the ATP driver.  This includes parameter blocks and buffer data structures
  20478. (BDS). The structure of the BDS is detailed in elsewhere in this chapter.  The exact
  20479. size of this memory depends on the size of the response expected, and, in the case of
  20480. UserWrite, on the size of data to be written.
  20481.  
  20482. In the UserCommand and GetStatus cases (along with all AFP calls which map to UserCommand),
  20483. a BDS must be set up to hold the response information.  The number of entries in this
  20484. BDS is equal to the size of the response buffer divided by the maximum number of data
  20485. bytes per ATP response packet (578), rounded up.  As described in the ASP chapter in
  20486. Inside AppleTalk, ASP must ask for an extra response in the case where the response
  20487. buffer is an exact multiple of 578.  Of course, no BDS can be larger than eight
  20488. elements.  XPP also needs bytes for the queue element to call ATP with, so the minimum
  20489. size of a CCB, as a function of the response buffer size (rbSize) is
  20490.  
  20491.   bdsSize = MIN (((rbSize DIV 578) + 1),8) * bdsEntrySz
  20492.   ccbSize = ioQElSize + 4 + bdsSize
  20493.  
  20494. With UserWrite (and AFP calls mapping to UserWrite), XPP must create an additional
  20495. BDS and queue element to use in sending the write data to the server.  Therefore the 
  20496. minimum size of a UserWrite CCB, as a function of the response buffer and write data
  20497. sizes (rbSize and wdSize) is:
  20498.  
  20499.   wrBDSSize = MIN (((wdSize DIV 578) + 1),8) * bdsEntrySz
  20500.   wrCCBSize = (2 * ioQElSize) + 4 + bdsSize + wrBDSSize
  20501.  
  20502. Note: BDSEntrySz is equal to 12; ioQelSize is equal to 50.
  20503.  
  20504. _______________________________________________________________________________
  20505.  
  20506. ».XPP Driver Result Codes
  20507.  
  20508. Result Code       Comment                                      Returned by
  20509.  
  20510. aspBadVersNum     Server cannot support the offered version    ASPOpenSession
  20511.                   number.                                      AFPCall (Login)
  20512.  
  20513. aspBufTooSmall    Reply is bigger than response buffer.        ASPUserWrite
  20514.                   Buffer will be filled, data may be           ASPUserCommand
  20515.                   truncated.                                   ASPGetStatus
  20516.                                                                AFPCall
  20517.  
  20518. aspNoMoreSess     Driver cannot support another session.       ASPOpenSessION 
  20519.                                                                AFPCall (Login)
  20520.  
  20521. aspNoServers      No servers at that address.                  ASPGetStatus
  20522.                   The server did not respond to the request.   ASPOpenSession
  20523.                                                                AFPCall (Login)
  20524.  
  20525. aspParamErr       Parameter error, server returned bad         ASPOpenSession 
  20526.                   (positive) error code.                       ASPCloseSess
  20527.                   Invalid Session Reference Number.            ASPUserWrite
  20528.                                                                ASPUserCommand
  20529.                                                                AFPCall
  20530.  
  20531. aspServerBusy     Server cannot open another session.          ASPOpenSession
  20532.                                                                AFPCall (Login)
  20533.  
  20534. aspSessClosed     Session already in process of closing.       ASPCloseSession
  20535.                                                                ASPUserWrite
  20536.                                                                ASPUserCommand
  20537.                                                                AFPCall
  20538.  
  20539. aspSizeErr        Command block size is bigger than            ASPUserWrite
  20540.                   maxParamSize.                                ASPUserCommand
  20541.                                                                AFPCall
  20542.  
  20543. cbNotFound        SCB not found, no outstanding                ASPAbortOS
  20544.                   open session to be aborted.  Pointer did
  20545.                   not point to an open session SCB.
  20546.  
  20547. afpParmError      AFP Command Block size is less than or       AFPCall
  20548.                   equal to zero.  Command byte in the
  20549.                   Command block is equal to 0 or $FF (255)
  20550.                   or GetSrvrStatus (15).
  20551.  
  20552. reqAborted        Open session was aborted by an               ASPOpenSession
  20553.                   Abort Open Session.                          AFPCall (Login)
  20554.  
  20555. _______________________________________________________________________________
  20556.  
  20557.  
  20558. æKY Protocol…Handlers…and…Socket…Listeners
  20559. æC »PROTOCOL HANDLERS AND SOCKET LISTENERS                   AppleTalkManager
  20560. _______________________________________________________________________________
  20561.  
  20562. This section describes how to write your own protocol handlers and socket listeners.
  20563. If you’re only interested in using the default protocol handlers and socket listeners
  20564. provided by the Pascal interface, you can skip this section. Protocol handlers and
  20565. socket listeners must be written in assembly language because they’ll be called by
  20566. the .MPP driver with parameters in various registers not directly accessible from
  20567. Pascal.
  20568.  
  20569. The .MPP and .ATP drivers have been designed to maximize overall throughput while
  20570. minimizing code size. Two principal sources of loss of throughput are unnecessary
  20571. buffer copying and inefficient mechanisms for dispatching (routing) packets between
  20572. the various layers of the network protocol architecture. The AppleTalk Manager completely
  20573. eliminates buffer copying by using simple, efficient dispatching mechanisms at two
  20574. important points of the data reception path:  protocol handlers and socket listeners.
  20575. To write your own, you should understand the flow of control in this path.
  20576.  
  20577. _______________________________________________________________________________
  20578.  
  20579. »Data Reception in the AppleTalk Manager
  20580.  
  20581. When the SCC detects an ALAP frame addressed to the particular node (or a broadcast
  20582. frame), it interrupts the Macintosh’s MC68000. An interrupt handler built into the
  20583. .MPP driver gets control and begins servicing the interrupt. Meanwhile, the frame’s
  20584. ALAP header bytes are coming into the SCC’s data reception buffer; this is a three-byte
  20585. FIFO buffer. The interrupt handler must remove these bytes from the SCC’s buffer to
  20586. make room for the bytes right behind; for this purpose, MPP has an internal buffer,
  20587. known as the Read Header Area (RHA), into which it places these three bytes.
  20588.  
  20589. The third byte of the frame contains the ALAP protocol type field. If the most significant
  20590. bit of this field is set (that is, ALAP protocol types 128 to 255), the frame is an
  20591. ALAP control frame. Since ALAP control frames are only three bytes long (plus two CRC
  20592. bytes), for such frames the interrupt handler simply confirms that the CRC bytes
  20593. indicate an error-free frame and then performs the specified action.
  20594.  
  20595. If, however, the frame being received is a data frame (that is, ALAP protocol types 1
  20596. to 127), intended for a higher layer of the protocol architecture implemented on that
  20597. Macintosh, this means that additional data bytes are coming right behind. The interrupt
  20598. handler must immediately pass control to the protocol handler corresponding to the
  20599. protocol type specified in the third byte of the ALAP frame for continued reception
  20600. of the frame. To allow for such a dispatching mechanism, the ALAP code in MPP maintains
  20601. a protocol table. This consists of a list of currently used ALAP protocol types with
  20602. the memory addresses of their corresponding protocol handlers. To allow MPP to transfer
  20603. control to a protocol handler you’ve written, you must make an appropriate entry in
  20604. the protocol table with a valid ALAP protocol type and the memory address of your
  20605. code module.
  20606.  
  20607. To enter your protocol handler into the protocol table, issue the LAPOpenProtocol
  20608. call from Pascal or an AttachPH call from assembly language. Thereafter, whenever an
  20609. ALAP header with your ALAP protocol type is received, MPP will call your protocol
  20610. handler. When you no longer wish to receive packets of that ALAP protocol type, call
  20611. LAPCloseProtocol from Pascal or DetachPH from assembly language.
  20612.  
  20613. Warning:  Remember that ALAP protocol types 1 and 2 are reserved by DDP
  20614.           for the default protocol handler and that types 128 to 255 are
  20615.           used by ALAP for its control frames.
  20616.  
  20617. A protocol handler is a piece of assembly-language code that controls the reception
  20618. of AppleTalk packets of a given ALAP protocol type. More specifically, a protocol
  20619. handler must carry out the reception of the rest of the frame following the ALAP
  20620. header. The nature of a particular protocol handler depends on the characteristics of
  20621. the protocol for which it was written. In the simplest case, the protocol handler
  20622. simply reads the entire packet into an internal buffer. A more sophisticated protocol
  20623. handler might read in the header of its protocol, and on the basis of information
  20624. contained in it, decide where to put the rest of the packet’s data. In certain cases,
  20625. the protocol handler might, after examining the header corresponding to its own
  20626. protocol, in turn transfer control to a similar piece of code at the next-higher
  20627. level of the protocol architecture (for example, in the case of DDP, its protocol
  20628. handler must call the socket listener of the datagram’s destination socket).
  20629.  
  20630. In this way, protocol handlers are used to allow “on the fly” decisions regarding the
  20631. intended recipient of the packets’s data, and thus avoid buffer copying. By using
  20632. protocol handlers and their counterparts in higher layers
  20633. (for instance, socket listeners), data sent over the AppleTalk network is read directly
  20634. from the network into the destination’s buffer.
  20635.  
  20636. _______________________________________________________________________________
  20637.  
  20638. »Writing Protocol Handlers
  20639.  
  20640. When the .MPP driver calls your protocol handler, it has already read the first five
  20641. bytes of the packet into the RHA. These are the three-byte ALAP header and the next
  20642. two bytes of the packet. The two bytes following the header must contain the length
  20643. in bytes of the data in the packet, including these two bytes themselves, but excluding
  20644. the ALAP header.
  20645.  
  20646. Note:  Since ALAP packets can have at most 600 data bytes, only the lower
  20647.        ten bits of this length value are significant.
  20648.  
  20649. After determining how many bytes to read and where to put them, the protocol handler
  20650. must call one or both of two functions that perform all the low-level manipulation of
  20651. the SCC required to read bytes from the network. ReadPacket can be called repeatedly
  20652. to read in the packet piecemeal or ReadRest can be called to read the rest of the
  20653. packet. Any number of ReadPacket calls can be used, as long as a ReadRest call is
  20654. made to read the final piece of the packet. This is necessary because ReadRest restores
  20655. state information and verifies that the hardware-generated CRC is correct. An error
  20656. will be returned if the protocol handler attempts to use ReadPacket to read more
  20657. bytes than remain in the packet.
  20658.  
  20659. When MPP passes control to your protocol handler, it passes various parameters and
  20660. pointers in the processor’s registers:
  20661.  
  20662.   Register(s)    Contents
  20663.  
  20664.   A0-A1          SCC addresses used by MPP
  20665.   A2             Pointer to MPP’s local variables (discussed below)
  20666.   A3             Pointer to next free byte in RHA
  20667.   A4             Pointer to ReadPacket and ReadRest jump table
  20668.   D1 (word)      Number of bytes left to read in packet
  20669.  
  20670. These registers, with the exception of A3, must be preserved until ReadRest is called.
  20671. A3 is used as an input parameter to ReadPacket and ReadRest, so its contents may be
  20672. changed. D0, D2, and D3 are free for your use. In addition, register A5 has been
  20673. saved by MPP and may be used by the protocol handler until ReadRest is called. When
  20674. control returns to the protocol handler from ReadRest, MPP no longer needs the data
  20675. in these registers. At that point, standard interrupt routine conventions apply and
  20676. the protocol handler can freely use
  20677. A0-A3 and D0-D3 (they’re restored by the interrupt handler).
  20678.  
  20679. D1 contains the number of bytes left to be read in the packet as derived from the
  20680. packet’s length field. A transmission error could corrupt the length field or some
  20681. bytes in the packet might be lost, but this won’t be discovered until the end of the
  20682. packet is reached and the CRC checked.
  20683.  
  20684. When the protocol handler is first called, the first five bytes of the packet
  20685. (ALAP destination node ID, source node ID, ALAP protocol type, and length) can be
  20686. read from the RHA. Since A3 is pointing to the next free position in the RHA, these
  20687. bytes can be read using negative offsets from A3. For instance, the ALAP source node
  20688. ID is at –4(A3), the packet’s data length (given in D1) is also pointed to by –2(A3),
  20689. and so on. Alternatively, they can be accessed as positive offsets from the top of
  20690. the RHA. The effective address of the top of the RHA is toRHA(A2), so the following
  20691. code could be used to obtain the ALAP type field:
  20692.  
  20693.   LEA       toRHA(A2),A5      ;A5 points to top of RHA
  20694.   MOVE.B    lapType(A5),D2    ;load D2 with type field
  20695.  
  20696. These methods are valid only as long as SCC interrupts remain locked out (which they
  20697. are when the protocol handler is first called). If the protocol handler lowers the
  20698. interrupt level, another packet could arrive over the network and invalidate the
  20699. contents of the RHA.
  20700.  
  20701. •••Refer to Technical Note #201:•••
  20702.  
  20703. You can call ReadPacket by jumping through the jump table in the following way:
  20704.  
  20705.   JSR (A4)
  20706.  
  20707.   On entry    D3:    number of bytes to be read (word)
  20708.               A3:    pointer to a buffer to hold the bytes
  20709.   On exit     D0:    modified
  20710.               D1:    number of bytes left to read in packet (word)
  20711.               D2:    preserved
  20712.               D3:    =  0 if requested number of bytes were read
  20713.                      <> 0 if error
  20714.               A0-A2: preserved
  20715.               A3:    pointer to one byte past the last byte read
  20716.  
  20717. ReadPacket reads the number of bytes specified in D3 into the buffer pointed to by
  20718. A3. The number of bytes remaining to be read in the packet is returned in D1. A3
  20719. points to the byte following the last byte read.
  20720.  
  20721. You can call ReadRest by jumping through the jump table in the following way:
  20722.  
  20723.   JSR 2(A4)
  20724.  
  20725.   On entry    A3:    pointer to a buffer to hold the bytes
  20726.               D3:    size of the buffer (word)
  20727.   On exit     D0-D1: modified
  20728.               D2:    preserved
  20729.               D3:    = 0 if packet was exactly the size of the buffer
  20730.                      < 0 if packet was (–D3) bytes too large to fit in
  20731.                          buffer and was truncated
  20732.                      > 0 if D3 bytes weren't read (packet is smaller
  20733.                          than buffer)
  20734.               A0-A2: preserved
  20735.               A3:    pointer to one byte past the last byte read
  20736.  
  20737. ReadRest reads the remaining bytes of the packet into the buffer whose size is given
  20738. in D3 and whose location is pointed to by A3. The result of the operation is returned
  20739. in D3.
  20740.  
  20741. ReadRest can be called with D3 set to a buffer size greater than the packet size;
  20742. ReadPacket cannot (it will return an error).
  20743.  
  20744. Warning:  Remember to always call ReadRest to read the last part of a
  20745.           packet; otherwise the system will eventually crash.
  20746.  
  20747. If at any point before it has read the last byte of a packet, the protocol handler
  20748. wants to discard the remaining data, it should terminate by calling ReadRest as
  20749. follows:
  20750.  
  20751.   MOVEQ    #0,D3    ;byte count of 0
  20752.   JSR      2(A4)    ;call ReadRest
  20753.   RTS
  20754.  
  20755. Or, equivalently:
  20756.  
  20757.   MOVEQ    #0,D3    ;byte count of 0
  20758.   JMP      2(A4)    ;JMP to ReadRest, not JSR
  20759.  
  20760. In all other cases, the protocol handler should end with an RTS, even if errors were
  20761. detected. If MPP returns an error from a ReadPacket call, the protocol handler must
  20762. quit via an RTS without calling ReadRest at all (in this case it has already been
  20763. called by MPP).
  20764.  
  20765. The Z (Zero) condition code is set upon return from these routines to indicate the
  20766. presence of errors (CRC, overrun, and so on). Zero bit set means no error was detected;
  20767. a nonzero condition code implies an error of some kind.
  20768.  
  20769. Up to 24 bytes of temporary storage are available in MPP’s RHA. When the protocol
  20770. handler is called, 19 of these bytes are free for its use. It may read several bytes
  20771. (at least four are suggested) into this area to empty the SCC’s buffer and buy some
  20772. time for further processing.
  20773.  
  20774. MPP’s globals include some variables that you may find useful. They’re allocated as a
  20775. block of memory pointed to by the contents of the global variable ABusVars, but a
  20776. protocol handler can access them by offsets from A2:
  20777.  
  20778.   Name          Contents
  20779.  
  20780.   sysLAPAddr    This node’s node ID (byte)
  20781.   toRHA         Top of the Read Header Area (24 bytes)
  20782.   sysABridge    Node ID of a bridge (byte)
  20783.   sysNetNum     This node’s network number (word)
  20784.   vSCCEnable    Status Register (SR) value to re-enable SCC interrupts (word)
  20785.  
  20786. Warning:  Under no circumstances should your protocol handler modify
  20787.           these variables. It can read them to find the node’s ID, its
  20788.           network number, and the node ID of a bridge on the AppleTalk internet.
  20789.  
  20790. If, after reading the entire packet from the network and using the data in the RHA,
  20791. the protocol handler needs to do extensive post-processing, it can load the value in
  20792. vSCCEnable into the SR to enable interrupts. To allow your programs to run transparently
  20793. on any Macintosh, use the value in vSCCEnable rather than directly manipulating the
  20794. interrupt level by changing specific bits in the SR.
  20795.  
  20796. Additional information, such as the driver’s version number or reference number and a
  20797. pointer (or handle) to the driver itself, may be obtained from MPP’s device control
  20798. entry. This can be found by dereferencing the handle in the unit table’s entry corresponding
  20799. to unit number 9; for more information, see the section “The Structure of a Device
  20800. Driver” in the Device Manager chapter.
  20801.  
  20802. »Timing Considerations
  20803.  
  20804. Once it’s been called by MPP, your protocol handler has complete responsibility for
  20805. receiving the rest of the packet. The operation of your protocol handler is time-critical.
  20806. Since it’s called just after MPP has emptied the SCC’s three-byte buffer, the protocol
  20807. handler has approximately 95 microseconds (best case) before it must call ReadPacket
  20808. or ReadRest. Failure to do so will result in an overrun of the SCC’s buffer and loss
  20809. of packet information. If, within that time, the protocol handler can’t determine
  20810. where to put the entire incoming packet, it should call ReadPacket to read at least
  20811. four bytes into some private buffer (possibly the RHA). Doing this will again empty
  20812. the SCC’s buffer and buy another 95 microseconds. You can do this as often as necessary,
  20813. as long as the processing time between successive calls to ReadPacket doesn’t exceed
  20814. 95 microseconds.
  20815.  
  20816. _______________________________________________________________________________
  20817.  
  20818. »Writing Socket Listeners
  20819.  
  20820. A socket listener is a piece of assembly-language code that receives datagrams delivered
  20821. by the DDP built-in protocol handler and delivers them to the client owning that
  20822. socket.
  20823.  
  20824. When a datagram (a packet with ALAP protocol type 1 or 2) is received by the ALAP,
  20825. DDP’s built-in protocol handler is called. This handler reads the DDP header into the
  20826. RHA, examines the destination socket number, and determines whether this socket is
  20827. open by searching DDP’s socket table. This table lists the socket number and corresponding
  20828. socket listener address for each open socket. If an entry is found matching the
  20829. destination socket, the protocol handler immediately transfers control to the appropriate
  20830. socket listener. (To allow DDP to recognize and branch to a socket listener you’ve
  20831. written, call DDPOpenSocket from Pascal or OpenSkt from assembly language.)
  20832.  
  20833. At this point, the registers are set up as follows:
  20834.  
  20835.   Register(s)    Contents
  20836.  
  20837.   A0-A1          SCC addresses used by MPP
  20838.   A2             Pointer to MPP’s local variables (discussed above)
  20839.   A3             Pointer to next free byte in RHA
  20840.   A4             Pointer to ReadPacket and ReadRest jump table
  20841.   D0             This packet’s destination socket number (byte)
  20842.   D1             Number of bytes left to read in packet (word)
  20843.  
  20844. The entire ALAP and DDP headers are in the RHA; these are the only bytes of the
  20845. packet that have been read in from the SCC’s buffer. The socket listener can get the
  20846. destination socket number from D0 to select a buffer into which the packet can be
  20847. read. The listener then calls ReadPacket and ReadRest as described under “Writing
  20848. Protocol Handlers” above. The timing considerations discussed in that section apply
  20849. as well, as do the issues related to accessing the MPP local variables.
  20850.  
  20851. The socket listener may examine the ALAP and DDP headers to extract the various
  20852. fields relevant to its particular client’s needs. To do so, it must first examine the
  20853. ALAP protocol type field (three bytes from the beginning of the RHA) to decide whether
  20854. a short (ALAP protocol type=1) or long (ALAP protocol type=2) header has been received.
  20855.  
  20856. A long DDP header containing a nonzero checksum field implies that the datagram was
  20857. checksummed at the source. In this case, the listener can recalculate the checksum
  20858. using the received datagram, and compare it with the checksum value. The following
  20859. subroutine can be used for this purpose:
  20860.  
  20861.   DoChksum    ;
  20862.               ; D1 (word) = number of bytes to checksum
  20863.               ; D3 (word) = current checksum
  20864.               ; A1 points to the bytes to checksum
  20865.               ;
  20866.               CLR.W     D0          ;clear high byte
  20867.               SUBQ.W    #1,D1       ;decrement count for DBRA
  20868.   Loop        MOVE.B    (A1)+,D0    ;read a byte into D0
  20869.               ADD.W     D0,D3       ;accumulate checksum
  20870.               ROL.W     #1,D3       ;rotate left one bit
  20871.               DBRA      D1,Loop     ;loop if more bytes
  20872.               RTS
  20873.  
  20874. Note:  D0 is modified by DoChksum.
  20875.  
  20876. The checksum must be computed for all bytes starting with the DDP header byte following
  20877. the checksum field up to the last data byte (not including the CRC bytes). The socket
  20878. listener must start by first computing the checksum for the DDP header fields in the
  20879. RHA. This is done as follows:
  20880.  
  20881.               CLR.W     D3          ;set checksum to 0
  20882.               MOVEQ     #ddpHSzLong-ddpDstNet,D1
  20883.                                     ;length of header part to checksum
  20884.               LEA       toRHA+lapHdSz+ddpDstNet(A2),A1
  20885.                                     ;point to destination network number
  20886.               JSR       DoChksum
  20887.               ; D3 = accumulated checksum of DDP header part
  20888.  
  20889. The socket listener must now continue to set up D1 and A1 for each subsequent portion
  20890. of the datagram, and call DoChksum for each. It must not alter the value in D3.
  20891.  
  20892. The situation of the calculated checksum being equal to 0 requires special attention.
  20893. For such packets, the source sends a value of –1 to distinguish them from unchecksummed
  20894. packets. At the end of its checksum computation, the socket listener must examine the
  20895. value in D3 to see if it’s 0. If so, it’s converted to –1 and compared with the
  20896. received checksum to determine whether there was a checksum error:
  20897.  
  20898.               TST.W     D3          ;is calculated value 0?
  20899.               BNE.S     @1          ;no -- go and use it
  20900.               SUBQ.W    #1,D3       ;it is 0; make it -1
  20901.   @1          CMP.W     toRHA+lapHdSz+ddpChecksum(A2),D3
  20902.               BNE       ChksumError
  20903.  
  20904. _______________________________________________________________________________
  20905.  
  20906.  
  20907. æKY Summary…of…the…AppleTalk…Manager
  20908. æC »SUMMARY OF THE APPLETALK MANAGER                         AppleTalkManager
  20909. _______________________________________________________________________________
  20910.  
  20911. Constants
  20912.  
  20913. CONST
  20914.   lapSize = 20;   {ABusRecord size for ALAP}
  20915.   ddpSize = 26;   {ABusRecord size for DDP}
  20916.   nbpSize = 26;   {ABusRecord size for NBP}
  20917.   atpSize = 56;   {ABusRecord size for ATP}
  20918.  
  20919. _______________________________________________________________________________
  20920.  
  20921. Data Types
  20922.  
  20923. TYPE
  20924.   ABProtoType = (lapProto,ddpProto,nbpProto,atpProto);
  20925.   ABRecHandle = ^ABRecPtr;
  20926.   ABRecPtr    = ^ABusRecord;
  20927.   ABusRecord  =
  20928.     RECORD
  20929.        abOpcode:        ABCallType;    {type of call}
  20930.        abResult:        INTEGER;       {result code}
  20931.        abUserReference: LONGINT;       {for your use}
  20932.        CASE ABProtoType OF
  20933.          lapProto:
  20934.           (lapAddress:  LAPAdrBlock; {destination or source node ID}
  20935.            lapReqCount: INTEGER;     {length of frame data or buffer size in }
  20936.                                      { bytes}
  20937.            lapActCount  INTEGER;     {number of frame data bytes actually }
  20938.                                      { received}
  20939.            lapDataPtr:  Ptr);        {pointer to frame data or pointer to }
  20940.                                      { buffer}
  20941.          ddpProto:
  20942.           (ddpType:     Byte;        {DDP protocol type}
  20943.            ddpSocket:   Byte;        {source or listening socket number}
  20944.            ddpAddress:  AddrBlock;   {destination or source socket address}
  20945.            ddpReqCount: INTEGER;     {length of datagram data or buffer size }
  20946.                                      { in bytes}
  20947.            ddpActCount: INTEGER;     {number of bytes actually received}
  20948.            ddpDataPtr:  Ptr;         {pointer to buffer}
  20949.            ddpNodeID:   Byte);       {original destination node ID}
  20950.          nbpProto:
  20951.           (nbpEntityPtr:     EntityPtr;    {pointer to entity name}
  20952.            nbpBufPtr:        Ptr;          {pointer to buffer}
  20953.            nbpBufSize:       INTEGER;      {buffer size in bytes}
  20954.            nbpDataField:     INTEGER;      {number of addresses or socket }
  20955.                                            { number}
  20956.            nbpAddress:       AddrBlock;    {socket address}
  20957.            nbpRetransmitInfo:RetransType); {retransmission information}
  20958.         atpProto:
  20959.          (atpSocket:     Byte;       {listening or responding socket number}
  20960.           atpAddress:    AddrBlock;  {destination or source socket address}
  20961.           atpReqCount:   INTEGER;    {request size or buffer size}
  20962.           atpDataPtr     Ptr;        {pointer to buffer}
  20963.           atpRspBDSPtr:  BDSPtr;     {pointer to response BDS}
  20964.           atpBitMap:     BitMapType; {transaction bit map}
  20965.           atpTransID:    INTEGER;    {transaction ID}
  20966.           atpActCount:   INTEGER;    {number of bytes actually received}
  20967.           atpUserData:   LONGINT;    {user bytes}
  20968.           atpXO:         BOOLEAN;    {exactly-once flag}
  20969.           atpEOM:        BOOLEAN;    {end-of-message flag}
  20970.           atpTimeOut:    Byte;       {retry timeout interval in seconds}
  20971.           atpRetries:    Byte;       {maximum number of retries}
  20972.           atpNumBufs:    Byte;       {number of elements in response BDS or }
  20973.                                      { number of response packets sent}
  20974.           atpNumRsp:     Byte;       {number of response packets received or }
  20975.                                      { sequence number}
  20976.           atpBDSSize:    Byte;       {number of elements in response BDS}
  20977.           atpRspUData:   LONGINT;    {user bytes sent or received in }
  20978.                                      { transaction response}
  20979.           atpRspBuf:     Ptr;        {pointer to response message buffer}
  20980.           atpRspSize:    INTEGER);   {size of response message buffer}
  20981.     END;
  20982.  
  20983.   ABCallType = (tLAPRead,tLAPWrite,tDDPRead,tDDPWrite,tNBPLookup,tNBPConfirm,
  20984.                 tNBPRegister,tATPSndRequest,tATPGetRequest,tATPSdRsp,tATPAddRsp,
  20985.                 tATPRequest,tATPResponse);
  20986.  
  20987.   LAPAdrBlock = PACKED RECORD
  20988.                   dstNodeID:    Byte;   {destination node ID}
  20989.                   srcNodeID:    Byte;   {source node ID}
  20990.                   lapProtType:  ABByte  {ALAP protocol type}
  20991.                 END;
  20992.  
  20993.   ABByte = 1..127; {ALAP protocol type}
  20994.   AddrBlock = PACKED RECORD
  20995.                 aNet:     INTEGER;  {network number}
  20996.                 aNode:    Byte;     {node ID}
  20997.                 aSocket:  Byte      {socket number}
  20998.               END;
  20999.  
  21000.   BDSPtr     = ^BDSType;
  21001.   BDSType    = ARRAY[0..7] OF BDSElement; {response BDS}
  21002.   BDSElement = RECORD
  21003.                  buffSize:   INTEGER;  {buffer size in bytes}
  21004.                  buffPtr:    Ptr;      {pointer to buffer}
  21005.                  dataSize:   INTEGER;  {number of bytes actually received}
  21006.                  userBytes:  LONGINT   {user bytes}
  21007.                END;
  21008.  
  21009.   BitMapType = PACKED ARRAY[0..7] OF BOOLEAN;
  21010.   EntityPtr  = ^EntityName;
  21011.   EntityName = RECORD
  21012.                  objStr:   Str32;  {object}
  21013.                  typeStr:  Str32;  {type}
  21014.                  zoneStr:  Str32    {zone}
  21015.                END;
  21016.  
  21017.   Str32 = STRING[32];
  21018.   RetransType =
  21019.       PACKED RECORD
  21020.         retransInterval:  Byte;  {retransmit interval in 8-tick units}
  21021.         retransCount:     Byte   {total number of attempts}
  21022.       END;
  21023.  
  21024.   MPPParamBlock = PACKED RECORD
  21025.        qLink:          QElemPtr;     {next queue entry}
  21026.        qType:          INTEGER;      {queue type}
  21027.        ioTrap:         INTEGER;      {routine trap}
  21028.        ioCmdAddr:      Ptr;          {routine address}
  21029.        ioCompletion:   ProcPtr;      {completion routine}
  21030.        ioResult:       OSErr;        {result code}
  21031.        ioNamePtr:      StringPtr;    {command result (ATP user bytes) [long]}
  21032.        ioVRefNum:      INTEGER;      {volume reference or drive number}
  21033.        ioRefNum:       INTEGER;      {driver reference number}
  21034.        csCode:         INTEGER;      {call command code AUTOMATICALLY SET}
  21035.  
  21036.        CASE MPPParmType OF
  21037.        LAPWriteParm:
  21038.                     (filler0:INTEGER;
  21039.                     wdsPointer:Ptr);    {->Write Data Structure}
  21040.        AttachPHParm,DetachPHParm:
  21041.                     (protType:Byte;     {ALAP Protocol Type}
  21042.                     filler1:Byte;
  21043.                     handler:Ptr);       {->protocol handler routine}
  21044.        OpenSktParm,CloseSktParm,WriteDDPParm:
  21045.                     (socket:Byte;       {socket number}
  21046.                     checksumFlag:Byte;  {checksum flag}
  21047.                     listener:Ptr);      {->socket listener routine}
  21048.        RegisterNameParm,LookupNameParm,ConfirmNameParm,RemoveNameParm:
  21049.                     (interval:Byte;     {retry interval}
  21050.                     count:Byte;         {retry count}
  21051.                     entityPtr:Ptr;      {->names table element or }
  21052.                                         { ->entity name}
  21053.                     CASE MPPParmType OF
  21054.                     RegisterNameParm:
  21055.                              (verifyFlag:Byte;     {set if verify needed}
  21056.                               filler3:Byte);
  21057.                     LookupNameParm:
  21058.                                     (retBuffPtr:Ptr;       {->return buffer}
  21059.                                     retBuffSize:INTEGER;   {return buffer size}
  21060.                                     maxToGet:INTEGER;      {matches to get}
  21061.                                     numGotten:INTEGER);    {matched gotten}
  21062.                     ConfirmNameParm:
  21063.                                     (confirmAddr:AddrBlock; {->entity}
  21064.                                     newSocket:Byte;         {socket number}
  21065.                                     filler4:Byte));
  21066.  
  21067.        SetSelfSendParm:
  21068.                     (newSelfFlag:Byte;  {self-send toggle flag}
  21069.                     oldSelfFlag:Byte);  {previous self-send state}
  21070.        KillNBPParm:
  21071.                     (nKillQEl:Ptr);     {ptr to Q element to cancel}
  21072.      END;
  21073.  
  21074. ATPParamBlock = PACKED RECORD
  21075.          qLink:            QElemPtr;    {next queue entry}
  21076.          qType:            INTEGER;     {queue type}
  21077.          ioTrap:           INTEGER;     {routine trap}
  21078.          ioCmdAddr:        Ptr;         {routine address}
  21079.          ioCompletion:     ProcPtr;     {completion routine}
  21080.          ioResult:         OSErr;       {result code}
  21081.          userData:         LONGINT;     {ATP user bytes [long]}
  21082.          reqTID:           INTEGER;     {request transaction ID}
  21083.          ioRefNum:         INTEGER;     {driver reference number
  21084.          csCode:           INTEGER;     {Call command code }
  21085.                                         { AUTOMATICALLY SET}
  21086.          atpSocket:        Byte;        {currBitMap or socket number}
  21087.          atpFlags:         Byte;        {control information}
  21088.          addrBlock:        AddrBlock;   {source/dest. socket address}
  21089.          reqLength:        INTEGER;     {request/response length}
  21090.          reqPointer:       Ptr;         {-> request/response data}
  21091.          bdsPointer:       Ptr;         {-> response BDS}
  21092.          CASE MPPParmType OF
  21093.                 SendRequestParm,NSendRequestParm:
  21094.                     (numOfBuffs:Byte;   {numOfBuffs}
  21095.                     timeOutVal:Byte;    {timeout interval}
  21096.                     numOfResps:Byte;    {number responses actually received}
  21097.                     retryCount:Byte;    {number of retries}
  21098.                     intBuff:INTEGER);   {used internally for NSendRequest}
  21099.                 SendResponseParm:
  21100.                     (filler0:Byte;      {number of responses being sent}
  21101.                     bdsSize:Byte;       {number of BDS elements}
  21102.                     transID:INTEGER);   {transaction ID}
  21103.                 GetRequestParm:
  21104.                     (bitMap:Byte;       {bit map}
  21105.                     filler1:Byte);
  21106.                 AddResponseParm:
  21107.                     (rspNum:Byte;       {sequence number}
  21108.                     filler2:Byte);
  21109.                 KillSendReqParm,KillGetReqParm:
  21110.                     (aKillQEl:Ptr);     {ptr to Q element to cancel}
  21111.          END;
  21112.  
  21113.   XPPParamBlock = PACKED RECORD
  21114.     qLink:         QElemPtr;  {next queue entry}
  21115.     qType:         INTEGER;   {queue type}
  21116.     ioTrap:        INTEGER;   {routine trap}
  21117.     ioCmdAddr:     Ptr;       {routine address}
  21118.     ioCompletion:  ProcPtr;   {completion routine}
  21119.     ioResult:      OSErr;     {result code}
  21120.     cmdResult:     LONGINT;   {command result (ATP user bytes) [long]}
  21121.     ioVRefNum:     INTEGER;   {volume reference or drive number)
  21122.     ioRefNum:      INTEGER;   {driver reference number)
  21123.     csCode:        INTEGER;   {Call command code}
  21124.     CASE XPPPrmBlkType OF
  21125.       ASPAbortPrm:
  21126.         (abortSCBPtr:    Ptr);      {SCB pointer for AbortOS [long]}
  21127.       ASPSizeBlk:
  21128.         (aspMaxCmdSize:  INTEGER;   {for SPGetParms [word]
  21129.         aspQuantumSize:  INTEGER;   {for SPGetParms [word]}
  21130.         numSesss:        INTEGER);  {for SPGetParms [word]}
  21131.       XPPPrmBlk:
  21132.         (sessRefnum:     INTEGER;   {offset to session refnum [word]}
  21133.         aspTimeout:      Byte;      {timeout for ATP [byte]}
  21134.         aspRetry:        Byte;      {retry count for ATP [byte]}
  21135.         CASE XPPSubPrmType OF
  21136.           ASPOpenPrm:
  21137.             (serverAddr:    AddrBlock;  {server address block [longword]}
  21138.             scbPointer:     Ptr;        {SCB pointer [longword]}
  21139.             attnRoutine:    Ptr);       {attention routine pointer [long]}
  21140.           ASPSubPrm:
  21141.             (cbSize:        INTEGER;    {command block size [word]}
  21142.             cbPtr:          Ptr;        {command block pointer [long]}
  21143.             rbSize:         INTEGER;    {reply buffer size [word]}
  21144.             rbPtr:          Ptr;        {reply buffer pointer [long]}
  21145.             CASE XPPEndPrmType OF
  21146.               AFPLoginPrm:
  21147.                 (afpAddrBlock:     AddrBlock;    {address block in}
  21148.                                                  { AFPlogin [long]}
  21149.                 afpSCBPtr:         Ptr;          {SCB pointer in }
  21150.                                                  { AFPlogin [long]}
  21151.                 afpAttnRoutine:    Ptr);         {attn routine pointer }
  21152.                                                  { in AFPlogin}
  21153.               ASPEndPrm:
  21154.                 (wdSize:           INTEGER;      {write data size [word]}
  21155.                 wdPtr:             Ptr;          {write data pointer [long]}
  21156.                 ccbStart:          ARRAY[0..295] OF Byte)));   {CCB memory }
  21157.                                                                { for driver}
  21158.      {Write max size(CCB) = 296; all other calls = 150}
  21159.      END;
  21160.  
  21161. AFPCommandBlock = PACKED RECORD
  21162.                     cmdByte:       Byte;
  21163.                     startEndFlag:  Byte;
  21164.                     forkRefNum:    INTEGER;    {used by server}
  21165.                     rwOf